From cec13ec29b9f3ebdc97123cc4d7e37ff3fb3e52d Mon Sep 17 00:00:00 2001 From: ykiko Date: Sun, 30 Nov 2025 15:21:27 +0800 Subject: [PATCH] refactor: tests and format the world (#314) --- .clang-format | 45 +- .github/workflows/cmake.yml | 1 + CMakeLists.txt | 2 +- bin/clice.cc | 10 +- bin/unit_tests.cc | 152 +-- cmake/package.cmake | 10 +- docs/semantic-tokens-example.cpp | 1 + include/AST/Context.h | 2 +- include/AST/FilterASTVisitor.h | 1 + include/AST/Resolver.h | 2 +- include/AST/Selection.h | 10 +- include/AST/Semantic.h | 7 +- include/AST/SourceCode.h | 9 +- include/AST/SymbolID.h | 2 +- include/AST/SymbolKind.h | 1 + include/Async/Async.h | 8 +- include/Async/Event.h | 1 + include/Async/FileSystem.h | 13 +- include/Async/Gather.h | 4 +- include/Async/Network.h | 5 +- include/Async/Sleep.h | 1 + include/Async/Task.h | 6 +- include/Async/libuv.h | 4 +- include/Compiler/Command.h | 4 +- include/Compiler/Compilation.h | 4 +- include/Compiler/CompilationUnit.h | 7 +- include/Compiler/Diagnostic.h | 2 + include/Compiler/Directive.h | 3 +- include/Compiler/Module.h | 3 +- include/Compiler/Preamble.h | 2 +- include/Compiler/Scan.h | 4 +- include/Compiler/Tidy.h | 6 +- include/Compiler/Toolchain.h | 2 +- include/Feature/CodeCompletion.h | 3 +- include/Feature/Formatting.h | 1 + include/Feature/Hover.h | 2 +- include/Feature/InlayHint.h | 2 +- include/Feature/Lookup.h | 2 +- include/Feature/SemanticToken.h | 2 +- include/Feature/SignatureHelp.h | 5 +- include/Index/IncludeGraph.h | 6 +- include/Index/MergedIndex.h | 7 +- include/Index/TUIndex.h | 7 +- include/Index/USR.h | 2 +- include/Protocol/Basic.h | 8 +- include/Protocol/Lifecycle.h | 2 +- include/Protocol/TextDocument.h | 12 +- include/Server/Config.h | 2 +- include/Server/Convert.h | 6 +- include/Server/Indexer.h | 1 - include/Server/Server.h | 4 +- include/Support/Binary.h | 10 +- include/Support/Compare.h | 6 +- include/Support/Doxygen.h | 6 +- include/Support/Enum.h | 28 +- include/Support/FileSystem.h | 9 +- include/Support/FixedString.h | 7 + include/Support/Format.h | 2 + include/Support/FuzzyMatcher.h | 1 + include/Support/GlobPattern.h | 2 +- include/Support/Hash.h | 1 + include/Support/JSON.h | 6 +- include/Support/Logging.h | 1 + include/Support/ObjectPool.h | 14 +- include/Support/Ranges.h | 2 +- include/Support/Struct.h | 4 +- include/Support/StructedText.h | 4 +- include/Test/Annotation.h | 157 +-- include/Test/LocationChain.h | 34 - include/Test/Platform.h | 2 +- include/Test/Runner.h | 49 + include/Test/TExpr.h | 110 -- include/Test/Test.h | 235 ++-- include/Test/Tester.h | 6 +- src/AST/Resolver.cpp | 12 +- src/AST/Selection.cpp | 11 +- src/AST/SymbolKind.cpp | 1 + src/AST/Utility.cpp | 17 +- src/Async/Async.cpp | 4 +- src/Async/FileSystem.cpp | 1 + src/Async/Network.cpp | 1 + src/Compiler/Command.cpp | 14 +- src/Compiler/Compilation.cpp | 18 +- src/Compiler/CompilationUnit.cpp | 2 +- src/Compiler/CompilationUnitImpl.h | 3 +- src/Compiler/Diagnostic.cpp | 10 +- src/Compiler/Directive.cpp | 3 +- src/Compiler/Driver.h | 3 +- src/Compiler/Module.cpp | 2 + src/Compiler/Preamble.cpp | 1 + src/Compiler/Tidy.cpp | 12 +- src/Compiler/TidyImpl.h | 3 +- src/Compiler/Toolchain.cpp | 12 +- src/Feature/CodeCompletion.cpp | 10 +- src/Feature/Diagnostic.cpp | 1 + src/Feature/DocumentLink.cpp | 5 +- src/Feature/DocumentSymbol.cpp | 6 +- src/Feature/FoldingRange.cpp | 4 +- src/Feature/Formatting.cpp | 4 +- src/Feature/Hover.cpp | 3 +- src/Feature/InlayHint.cpp | 8 +- src/Feature/SemanticToken.cpp | 5 +- src/Feature/SignatureHelp.cpp | 6 +- src/Index/IncludeGraph.cpp | 1 + src/Index/MergedIndex.cpp | 18 +- src/Index/ProjectIndex.cpp | 3 +- src/Index/Serialization.h | 3 +- src/Index/TUIndex.cpp | 4 +- src/Index/USRGeneration.cpp | 3 + src/Server/Config.cpp | 7 +- src/Server/Convert.cpp | 5 +- src/Server/Document.cpp | 9 +- src/Server/Feature.cpp | 12 +- src/Server/Indexer.cpp | 2 +- src/Server/Server.cpp | 3 +- src/Support/Doxygen.cpp | 7 +- src/Support/FuzzyMatcher.cpp | 1 + src/Support/GlobPattern.cpp | 5 +- src/Support/Logging.cpp | 5 +- tests/unit/AST/Resolver.cpp | 476 -------- tests/unit/AST/ResolverTests.cpp | 476 ++++++++ tests/unit/AST/Selection.cpp | 772 ------------- tests/unit/AST/SelectionTests.cpp | 775 +++++++++++++ ...icVisitor.cpp => SemanticVisitorTests.cpp} | 0 tests/unit/AST/SourceCode.cpp | 91 -- tests/unit/AST/SourceCodeTests.cpp | 94 ++ tests/unit/Async/Event.cpp | 68 -- tests/unit/Async/EventTests.cpp | 66 ++ tests/unit/Async/FileSystem.cpp | 47 - tests/unit/Async/FileSystemTests.cpp | 45 + tests/unit/Async/Gather.cpp | 70 -- tests/unit/Async/GatherTests.cpp | 70 ++ tests/unit/Async/Lock.cpp | 82 -- tests/unit/Async/LockTests.cpp | 80 ++ tests/unit/Async/Sleep.cpp | 26 - tests/unit/Async/SleepTests.cpp | 24 + tests/unit/Async/Task.cpp | 129 --- tests/unit/Async/TaskTests.cpp | 127 +++ tests/unit/Async/ThreadPool.cpp | 43 - tests/unit/Async/ThreadPoolTests.cpp | 41 + tests/unit/Compiler/Command.cpp | 329 ------ tests/unit/Compiler/CommandTests.cpp | 323 ++++++ tests/unit/Compiler/Compiler.cpp | 68 -- tests/unit/Compiler/CompilerTests.cpp | 72 ++ .../{Diagnostic.cpp => DiagnosticTests.cpp} | 100 +- tests/unit/Compiler/Directive.cpp | 202 ---- tests/unit/Compiler/DirectiveTests.cpp | 204 ++++ .../Compiler/{Module.cpp => ModuleTests.cpp} | 113 +- tests/unit/Compiler/Preamble.cpp | 294 ----- tests/unit/Compiler/PreambleTests.cpp | 295 +++++ tests/unit/Compiler/Tidy.cpp | 32 - tests/unit/Compiler/TidyTests.cpp | 32 + tests/unit/Compiler/Toolchain.cpp | 126 -- tests/unit/Compiler/ToolchainTests.cpp | 125 ++ tests/unit/Feature/CodeCompletion.cpp | 95 -- tests/unit/Feature/CodeCompletionTests.cpp | 94 ++ tests/unit/Feature/DocumentLink.cpp | 83 -- tests/unit/Feature/DocumentLinkTests.cpp | 82 ++ tests/unit/Feature/DocumentSymbol.cpp | 175 --- tests/unit/Feature/DocumentSymbolTests.cpp | 174 +++ tests/unit/Feature/FoldingRange.cpp | 407 ------- tests/unit/Feature/FoldingRangeTests.cpp | 406 +++++++ tests/unit/Feature/Formatting.cpp | 17 - tests/unit/Feature/FormattingTests.cpp | 15 + tests/unit/Feature/Hover.cpp | 408 ------- tests/unit/Feature/HoverTests.cpp | 408 +++++++ .../{InlayHint.cpp => InlayHintTests.cpp} | 1012 ++++++++--------- tests/unit/Feature/SemanticToken.cpp | 194 ---- tests/unit/Feature/SemanticTokenTests.cpp | 197 ++++ tests/unit/Feature/SignatureHelp.cpp | 43 - tests/unit/Feature/SignatureHelpTests.cpp | 42 + .../Index/{Function.cpp => FunctionTests.cpp} | 0 tests/unit/Index/MergedIndex.cpp | 78 -- tests/unit/Index/MergedIndexTests.cpp | 78 ++ ...ProjectIndex.cpp => ProjectIndexTests.cpp} | 0 tests/unit/Index/TUIndex.cpp | 253 ----- tests/unit/Index/TUIndexTests.cpp | 246 ++++ tests/unit/Index/USR.cpp | 351 ------ tests/unit/Index/USRTests.cpp | 355 ++++++ tests/unit/Server/ActiveFileManager.cpp | 108 -- tests/unit/Server/ActiveFileManagerTests.cpp | 115 ++ tests/unit/Support/Binary.cpp | 213 ---- tests/unit/Support/BinaryTests.cpp | 217 ++++ tests/unit/Support/Compare.cpp | 67 -- tests/unit/Support/CompareTests.cpp | 69 ++ tests/unit/Support/Doxygen.cpp | 329 ------ tests/unit/Support/DoxygenTests.cpp | 327 ++++++ tests/unit/Support/Enum.cpp | 148 --- tests/unit/Support/EnumTests.cpp | 149 +++ tests/unit/Support/GlobPattern.cpp | 498 -------- tests/unit/Support/GlobPatternTests.cpp | 501 ++++++++ tests/unit/Support/JSON.cpp | 194 ---- tests/unit/Support/JSONTests.cpp | 196 ++++ tests/unit/Support/Struct.cpp | 155 --- tests/unit/Support/StructTests.cpp | 155 +++ tests/unit/Support/StructedText.cpp | 121 -- tests/unit/Support/StructedTextTests.cpp | 121 ++ tests/unit/Test/Annotation.cpp | 159 +++ tests/unit/Test/Example.cpp | 36 - tests/unit/Test/Runner.cpp | 194 ++++ xmake.lua | 3 +- 201 files changed, 8302 insertions(+), 8277 deletions(-) delete mode 100644 include/Test/LocationChain.h create mode 100644 include/Test/Runner.h delete mode 100644 include/Test/TExpr.h delete mode 100644 tests/unit/AST/Resolver.cpp create mode 100644 tests/unit/AST/ResolverTests.cpp delete mode 100644 tests/unit/AST/Selection.cpp create mode 100644 tests/unit/AST/SelectionTests.cpp rename tests/unit/AST/{SemanticVisitor.cpp => SemanticVisitorTests.cpp} (100%) delete mode 100644 tests/unit/AST/SourceCode.cpp create mode 100644 tests/unit/AST/SourceCodeTests.cpp delete mode 100644 tests/unit/Async/Event.cpp create mode 100644 tests/unit/Async/EventTests.cpp delete mode 100644 tests/unit/Async/FileSystem.cpp create mode 100644 tests/unit/Async/FileSystemTests.cpp delete mode 100644 tests/unit/Async/Gather.cpp create mode 100644 tests/unit/Async/GatherTests.cpp delete mode 100644 tests/unit/Async/Lock.cpp create mode 100644 tests/unit/Async/LockTests.cpp delete mode 100644 tests/unit/Async/Sleep.cpp create mode 100644 tests/unit/Async/SleepTests.cpp delete mode 100644 tests/unit/Async/Task.cpp create mode 100644 tests/unit/Async/TaskTests.cpp delete mode 100644 tests/unit/Async/ThreadPool.cpp create mode 100644 tests/unit/Async/ThreadPoolTests.cpp delete mode 100644 tests/unit/Compiler/Command.cpp create mode 100644 tests/unit/Compiler/CommandTests.cpp delete mode 100644 tests/unit/Compiler/Compiler.cpp create mode 100644 tests/unit/Compiler/CompilerTests.cpp rename tests/unit/Compiler/{Diagnostic.cpp => DiagnosticTests.cpp} (65%) delete mode 100644 tests/unit/Compiler/Directive.cpp create mode 100644 tests/unit/Compiler/DirectiveTests.cpp rename tests/unit/Compiler/{Module.cpp => ModuleTests.cpp} (56%) delete mode 100644 tests/unit/Compiler/Preamble.cpp create mode 100644 tests/unit/Compiler/PreambleTests.cpp delete mode 100644 tests/unit/Compiler/Tidy.cpp create mode 100644 tests/unit/Compiler/TidyTests.cpp delete mode 100644 tests/unit/Compiler/Toolchain.cpp create mode 100644 tests/unit/Compiler/ToolchainTests.cpp delete mode 100644 tests/unit/Feature/CodeCompletion.cpp create mode 100644 tests/unit/Feature/CodeCompletionTests.cpp delete mode 100644 tests/unit/Feature/DocumentLink.cpp create mode 100644 tests/unit/Feature/DocumentLinkTests.cpp delete mode 100644 tests/unit/Feature/DocumentSymbol.cpp create mode 100644 tests/unit/Feature/DocumentSymbolTests.cpp delete mode 100644 tests/unit/Feature/FoldingRange.cpp create mode 100644 tests/unit/Feature/FoldingRangeTests.cpp delete mode 100644 tests/unit/Feature/Formatting.cpp create mode 100644 tests/unit/Feature/FormattingTests.cpp delete mode 100644 tests/unit/Feature/Hover.cpp create mode 100644 tests/unit/Feature/HoverTests.cpp rename tests/unit/Feature/{InlayHint.cpp => InlayHintTests.cpp} (61%) delete mode 100644 tests/unit/Feature/SemanticToken.cpp create mode 100644 tests/unit/Feature/SemanticTokenTests.cpp delete mode 100644 tests/unit/Feature/SignatureHelp.cpp create mode 100644 tests/unit/Feature/SignatureHelpTests.cpp rename tests/unit/Index/{Function.cpp => FunctionTests.cpp} (100%) delete mode 100644 tests/unit/Index/MergedIndex.cpp create mode 100644 tests/unit/Index/MergedIndexTests.cpp rename tests/unit/Index/{ProjectIndex.cpp => ProjectIndexTests.cpp} (100%) delete mode 100644 tests/unit/Index/TUIndex.cpp create mode 100644 tests/unit/Index/TUIndexTests.cpp delete mode 100644 tests/unit/Index/USR.cpp create mode 100644 tests/unit/Index/USRTests.cpp delete mode 100644 tests/unit/Server/ActiveFileManager.cpp create mode 100644 tests/unit/Server/ActiveFileManagerTests.cpp delete mode 100644 tests/unit/Support/Binary.cpp create mode 100644 tests/unit/Support/BinaryTests.cpp delete mode 100644 tests/unit/Support/Compare.cpp create mode 100644 tests/unit/Support/CompareTests.cpp delete mode 100644 tests/unit/Support/Doxygen.cpp create mode 100644 tests/unit/Support/DoxygenTests.cpp delete mode 100644 tests/unit/Support/Enum.cpp create mode 100644 tests/unit/Support/EnumTests.cpp delete mode 100644 tests/unit/Support/GlobPattern.cpp create mode 100644 tests/unit/Support/GlobPatternTests.cpp delete mode 100644 tests/unit/Support/JSON.cpp create mode 100644 tests/unit/Support/JSONTests.cpp delete mode 100644 tests/unit/Support/Struct.cpp create mode 100644 tests/unit/Support/StructTests.cpp delete mode 100644 tests/unit/Support/StructedText.cpp create mode 100644 tests/unit/Support/StructedTextTests.cpp create mode 100644 tests/unit/Test/Annotation.cpp delete mode 100644 tests/unit/Test/Example.cpp create mode 100644 tests/unit/Test/Runner.cpp diff --git a/.clang-format b/.clang-format index 814c1fb8..e8e61469 100644 --- a/.clang-format +++ b/.clang-format @@ -73,7 +73,7 @@ SpaceBeforeParensOptions: AfterFunctionDeclarationName: false AfterFunctionDefinitionName: false AfterIfMacros: false - AfterOverloadedOperator: true + AfterOverloadedOperator: false AfterRequiresInClause: true AfterRequiresInExpression: false BeforeNonEmptyParentheses: false @@ -93,11 +93,50 @@ SpacesInParensOptions: SpacesInSquareBrackets: false +WrapNamespaceBodyWithEmptyLines: Always # Order QualifierAlignment: Custom QualifierOrder: ["constexpr", "const", "inline", "static", "type"] -SortIncludes: Never +SortIncludes: true SortUsingDeclarations: Never -IncludeBlocks: Merge +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^["<](spdlog|toml\+\+|coraing|cpptrace|flatbuffers)/' + Priority: 30 + SortPriority: 31 + + - Regex: '^["<](llvm)/' + Priority: 30 + SortPriority: 32 + + - Regex: '^["<](clang)/' + Priority: 30 + SortPriority: 33 + + - Regex: '^["<](clang-tidy)/' + Priority: 30 + SortPriority: 34 + + - Regex: '^["<](Test)/' + Priority: 20 + SortPriority: 22 + + - Regex: "^<.*" + Priority: 10 + SortPriority: 10 + + - Regex: '^".*/.*"' + Priority: 20 + SortPriority: 23 + + - Regex: ".*" + Priority: 20 + SortPriority: 21 ForEachMacros: ["REFLECTABLE_RECORD"] +NamespaceMacros: [TEST_SUITE] + +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: false + AtStartOfFile: false diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 0d2c45b4..dd888d4a 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -80,6 +80,7 @@ jobs: shell: bash run: | if [[ "${{ runner.os }}" == "macOS" ]]; then + export SDKROOT=$(xcrun --show-sdk-path) export PATH="/opt/homebrew/opt/llvm@20/bin:/opt/homebrew/opt/lld@20/bin:$PATH" fi diff --git a/CMakeLists.txt b/CMakeLists.txt index dd9552fb..b45ecc7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,5 +149,5 @@ if(CLICE_ENABLE_TEST) "${PROJECT_SOURCE_DIR}/bin/unit_tests.cc" ) target_include_directories(unit_tests PUBLIC "${PROJECT_SOURCE_DIR}") - target_link_libraries(unit_tests PRIVATE clice-core) + target_link_libraries(unit_tests PRIVATE clice-core cpptrace::cpptrace) endif() diff --git a/bin/clice.cc b/bin/clice.cc index 1885fbc8..f94e1298 100644 --- a/bin/clice.cc +++ b/bin/clice.cc @@ -1,12 +1,12 @@ -#include "Server/Version.h" #include "Server/Server.h" -#include "Support/Logging.h" +#include "Server/Version.h" #include "Support/Format.h" +#include "Support/Logging.h" -#include "llvm/Support/InitLLVM.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Process.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/Process.h" namespace cl = llvm::cl; using namespace clice; diff --git a/bin/unit_tests.cc b/bin/unit_tests.cc index aee1d1a8..d626b0f4 100644 --- a/bin/unit_tests.cc +++ b/bin/unit_tests.cc @@ -1,6 +1,6 @@ #include "Test/Test.h" -#include "Support/Logging.h" #include "Support/GlobPattern.h" +#include "Support/Logging.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/CommandLine.h" @@ -9,11 +9,6 @@ using namespace clice; using namespace clice::testing; -constexpr static std::string_view GREEN = "\033[32m"; -constexpr static std::string_view YELLOW = "\033[33m"; -constexpr static std::string_view RED = "\033[31m"; -constexpr static std::string_view CLEAR = "\033[0m"; - namespace { namespace cl = llvm::cl; @@ -40,145 +35,8 @@ cl::opt enable_example{ cl::cat(unittest_category), }; -std::optional pattern; - } // namespace -namespace clice::testing { - -Runner& Runner::instance() { - static Runner runner; - return runner; -} - -void Runner::add_suite(std::string_view name, Suite suite) { - suites[name].emplace_back(suite); -} - -void Runner::on_test(std::string_view name, Test test, bool skipped) { - std::string full_name = std::format("{}.{}", curr_suite_name, name); - - /// If this test if filter, directly return. - if(pattern && !pattern->match(full_name)) { - return; - } - - /// If there is any test in the suite, we print the suite start info. - if(all_skipped) { - std::println("{}[----------] tests from {}{}", GREEN, curr_suite_name, CLEAR); - all_skipped = false; - } - - if(skipped) { - /// If this test is marked as skipped, only print skip information. - std::println("{}[ SKIPPED ] {}{}", YELLOW, full_name, CLEAR); - return; - } - - /// Reset whether this test is failed or fatal. - curr_failed = false; - curr_fatal = false; - - using namespace std::chrono; - - std::println("{}[ RUN ] {}.{}{}", GREEN, curr_suite_name, name, CLEAR); - auto begin = system_clock::now(); - - test(); - - auto duration = duration_cast(system_clock::now() - begin); - std::println("{}[ {} ] {} ({} ms){}", - curr_failed ? RED : GREEN, - curr_failed ? "FAILED" : " OK", - full_name, - duration.count(), - CLEAR); - - /// Update test information. - curr_tests_count += 1; - total_tests_count += 1; - - curr_test_duration += duration; - total_test_duration += duration; - - if(curr_failed) { - curr_failed_tests_count += 1; - total_failed_tests_count += 1; - } -} - -void Runner::fail(const may_failure& failure) { - if(failure.failed) { - curr_failed = true; - std::println("{}Failure at {}:{}:{}! [{}]{}", - RED, - failure.location.file_name(), - failure.location.line(), - failure.location.column(), - failure.expression, - CLEAR); - std::println("{}", failure.message); - } - - if(failure.fatal) { - curr_fatal = true; - std::println("{}--> Test stopped due to fatal error.{}", RED, CLEAR); - std::exit(1); - } -} - -int Runner::run_tests() { - /// Register all tests. - std::println("{}[----------] Global test environment set-up.{}", GREEN, CLEAR); - - for(auto& [suite_name, suite]: suites) { - if(!enable_example && suite_name == "TEST.Example") { - continue; - } - - if(!test_filter.empty()) { - auto pos = test_filter.find_first_of('.'); - if(pos != std::string::npos && test_filter.substr(0, pos) != suite_name) { - continue; - } - } - - curr_fatal = false; - all_skipped = true; - curr_suite_name = suite_name; - curr_tests_count = 0; - curr_failed_tests_count = 0; - curr_test_duration = std::chrono::milliseconds(); - - for(auto& callback: suite) { - callback(); - } - - /// If there is any test in the suite, we print the suite info. - if(!all_skipped) { - total_suites_count += 1; - std::println("{}[----------] {} tests from {} ({} ms total)\n{}", - GREEN, - curr_tests_count, - suite_name, - total_test_duration.count(), - CLEAR); - } - } - - std::println("{}[----------] Global test environment tear-down{}", GREEN, CLEAR); - std::println("{}[==========] {} tests from {} test suites ran. ({} ms total){}", - GREEN, - total_tests_count, - total_suites_count, - total_test_duration.count(), - CLEAR); - - return total_failed_tests_count != 0; -} - -} // namespace clice::testing - int main(int argc, const char* argv[]) { llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); llvm::cl::HideUnrelatedOptions(unittest_category); @@ -186,17 +44,11 @@ int main(int argc, const char* argv[]) { logging::stderr_logger("clice", logging::options); - if(!test_filter.empty()) { - if(auto result = GlobPattern::create(test_filter)) { - pattern.emplace(std::move(*result)); - } - } - if(auto result = fs::init_resource_dir(argv[0]); !result) { std::println("Failed to get resource directory, because {}", result.error()); return 1; } using namespace clice::testing; - return Runner::instance().run_tests(); + return Runner2::instance().run_tests(test_filter); } diff --git a/cmake/package.cmake b/cmake/package.cmake index 3df35f47..dfd62e63 100644 --- a/cmake/package.cmake +++ b/cmake/package.cmake @@ -117,6 +117,7 @@ FetchContent_Declare( GIT_TAG v4.4.2 ) set(ENABLE_ROARING_TESTS OFF CACHE INTERNAL "" FORCE) +set(ENABLE_ROARING_MICROBENCHMARKS OFF CACHE INTERNAL "" FORCE) # flatbuffers FetchContent_Declare( @@ -128,7 +129,14 @@ set(FLATBUFFERS_BUILD_GRPC OFF CACHE BOOL "" FORCE) set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(FLATBUFFERS_BUILD_FLATHASH OFF CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(libuv spdlog tomlplusplus croaring flatbuffers) +# cpptrace +FetchContent_Declare( + cpptrace + GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git + GIT_TAG v1.0.4 +) + +FetchContent_MakeAvailable(libuv spdlog tomlplusplus croaring flatbuffers cpptrace) if(WIN32) target_compile_definitions(uv_a PRIVATE _CRT_SECURE_NO_WARNINGS) diff --git a/docs/semantic-tokens-example.cpp b/docs/semantic-tokens-example.cpp index 8bb69c6a..4df7a814 100644 --- a/docs/semantic-tokens-example.cpp +++ b/docs/semantic-tokens-example.cpp @@ -58,4 +58,5 @@ struct Widget { template Widget(T) -> Widget; + } // namespace foo diff --git a/include/AST/Context.h b/include/AST/Context.h index ecea0d7c..26a8fb07 100644 --- a/include/AST/Context.h +++ b/include/AST/Context.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include namespace clice { diff --git a/include/AST/FilterASTVisitor.h b/include/AST/FilterASTVisitor.h index 6f240852..7c036002 100644 --- a/include/AST/FilterASTVisitor.h +++ b/include/AST/FilterASTVisitor.h @@ -2,6 +2,7 @@ #include "AST/SourceCode.h" #include "Compiler/CompilationUnit.h" + #include "clang/AST/RecursiveASTVisitor.h" namespace clice { diff --git a/include/AST/Resolver.h b/include/AST/Resolver.h index f0395e7d..525c4bab 100644 --- a/include/AST/Resolver.h +++ b/include/AST/Resolver.h @@ -1,7 +1,7 @@ #pragma once -#include "clang/AST/Type.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/Type.h" namespace clang { diff --git a/include/AST/Selection.h b/include/AST/Selection.h index 16bbbac4..39b34127 100644 --- a/include/AST/Selection.h +++ b/include/AST/Selection.h @@ -1,11 +1,13 @@ #pragma once #include + #include "SourceCode.h" + +#include "llvm/ADT/SmallVector.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/PrettyPrinter.h" #include "clang/Tooling/Syntax/Tokens.h" -#include "llvm/ADT/SmallVector.h" namespace clice { @@ -57,11 +59,11 @@ public: /// Copies are no good - contain pointers to other nodes. SelectionTree(const SelectionTree&) = delete; - SelectionTree& operator= (const SelectionTree&) = delete; + SelectionTree& operator=(const SelectionTree&) = delete; /// Moves are OK though - internal storage is pointer-stable when moved. SelectionTree(SelectionTree&&) = default; - SelectionTree& operator= (SelectionTree&&) = default; + SelectionTree& operator=(SelectionTree&&) = default; // Describes to what extent an AST node is covered by the selection. enum SelectionKind : unsigned char { @@ -129,7 +131,7 @@ public: void print(llvm::raw_ostream& os, const Node& node, int indent) const; - friend llvm::raw_ostream& operator<< (llvm::raw_ostream& os, const SelectionTree& tree) { + friend llvm::raw_ostream& operator<<(llvm::raw_ostream& os, const SelectionTree& tree) { tree.print(os, tree.root(), 1); return os; } diff --git a/include/AST/Semantic.h b/include/AST/Semantic.h index 394ac3aa..12cbf943 100644 --- a/include/AST/Semantic.h +++ b/include/AST/Semantic.h @@ -1,10 +1,10 @@ #pragma once -#include "Utility.h" +#include "FilterASTVisitor.h" +#include "RelationKind.h" #include "Resolver.h" #include "SymbolKind.h" -#include "RelationKind.h" -#include "FilterASTVisitor.h" +#include "Utility.h" namespace clice { @@ -637,7 +637,6 @@ public: } bool VisitAttr(clang::Attr* attr) { - getDerived().handleAttrOccurrence(attr, attr->getRange()); return true; } diff --git a/include/AST/SourceCode.h b/include/AST/SourceCode.h index e9e18cdb..771fc832 100644 --- a/include/AST/SourceCode.h +++ b/include/AST/SourceCode.h @@ -1,8 +1,9 @@ #pragma once #include -#include "clang/Lex/Token.h" + #include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Token.h" namespace std { @@ -46,7 +47,7 @@ struct LocalSourceRange { /// The end position offset to the source file. uint32_t end = static_cast(-1); - constexpr bool operator== (const LocalSourceRange& other) const = default; + constexpr bool operator==(const LocalSourceRange& other) const = default; constexpr auto length() { return end - begin; @@ -128,9 +129,9 @@ public: Lexer(Lexer&&) = delete; - Lexer& operator= (const Lexer&) = delete; + Lexer& operator=(const Lexer&) = delete; - Lexer& operator= (Lexer&&) = delete; + Lexer& operator=(Lexer&&) = delete; ~Lexer(); diff --git a/include/AST/SymbolID.h b/include/AST/SymbolID.h index 4f4eb07e..dffc3413 100644 --- a/include/AST/SymbolID.h +++ b/include/AST/SymbolID.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include namespace clice::index { diff --git a/include/AST/SymbolKind.h b/include/AST/SymbolKind.h index 1e659b16..682f2d2e 100644 --- a/include/AST/SymbolKind.h +++ b/include/AST/SymbolKind.h @@ -1,6 +1,7 @@ #pragma once #include "Support/Enum.h" + #include "clang/AST/Decl.h" namespace clice { diff --git a/include/Async/Async.h b/include/Async/Async.h index 48764838..f249b780 100644 --- a/include/Async/Async.h +++ b/include/Async/Async.h @@ -1,10 +1,10 @@ #pragma once -#include "Lock.h" #include "Event.h" -#include "Sleep.h" -#include "Gather.h" -#include "Network.h" #include "FileSystem.h" +#include "Gather.h" +#include "Lock.h" +#include "Network.h" +#include "Sleep.h" #include "ThreadPool.h" #include "libuv.h" diff --git a/include/Async/Event.h b/include/Async/Event.h index fce080a6..e5fbf6d9 100644 --- a/include/Async/Event.h +++ b/include/Async/Event.h @@ -1,6 +1,7 @@ #pragma once #include "Task.h" + #include "llvm/ADT/ArrayRef.h" namespace clice::async { diff --git a/include/Async/FileSystem.h b/include/Async/FileSystem.h index cc898488..318c3f45 100644 --- a/include/Async/FileSystem.h +++ b/include/Async/FileSystem.h @@ -3,15 +3,14 @@ #include #include -#include "libuv.h" -#include "Task.h" #include "Awaiter.h" - -#include "Support/JSON.h" +#include "Task.h" +#include "libuv.h" #include "Support/Enum.h" +#include "Support/JSON.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/StringRef.h" namespace clice::async { @@ -56,9 +55,9 @@ public: ~handle(); - handle& operator= (const handle&) = delete; + handle& operator=(const handle&) = delete; - handle& operator= (handle&& other) noexcept = delete; + handle& operator=(handle&& other) noexcept = delete; int value() const { return file; diff --git a/include/Async/Gather.h b/include/Async/Gather.h index 1c5a5076..f4117b3f 100644 --- a/include/Async/Gather.h +++ b/include/Async/Gather.h @@ -1,10 +1,10 @@ #pragma once -#include #include +#include -#include "Task.h" #include "Event.h" +#include "Task.h" namespace clice::async { diff --git a/include/Async/Network.h b/include/Async/Network.h index 1e3cc486..b5dc2933 100644 --- a/include/Async/Network.h +++ b/include/Async/Network.h @@ -1,12 +1,11 @@ #pragma once -#include "libuv.h" - #include "Task.h" +#include "libuv.h" #include "Support/JSON.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/StringRef.h" namespace clice::async::net { diff --git a/include/Async/Sleep.h b/include/Async/Sleep.h index 6dd35a8e..101bc643 100644 --- a/include/Async/Sleep.h +++ b/include/Async/Sleep.h @@ -1,6 +1,7 @@ #pragma once #include + #include "Awaiter.h" namespace clice::async { diff --git a/include/Async/Task.h b/include/Async/Task.h index 7c506e2a..78a4f88c 100644 --- a/include/Async/Task.h +++ b/include/Async/Task.h @@ -1,10 +1,10 @@ #pragma once #include +#include #include #include #include -#include #include #include "Support/Format.h" @@ -247,9 +247,9 @@ public: other.core = nullptr; } - Task& operator= (const Task&) = delete; + Task& operator=(const Task&) = delete; - Task& operator= (Task&& other) noexcept { + Task& operator=(Task&& other) noexcept { if(core) { core.destroy(); } diff --git a/include/Async/libuv.h b/include/Async/libuv.h index 49949644..02746a8f 100644 --- a/include/Async/libuv.h +++ b/include/Async/libuv.h @@ -12,11 +12,11 @@ #include #include -#include #include +#include -#include "Support/TypeTraits.h" #include "Support/Logging.h" +#include "Support/TypeTraits.h" namespace clice::async { diff --git a/include/Compiler/Command.h b/include/Compiler/Command.h index 73fb3cf0..58c61966 100644 --- a/include/Compiler/Command.h +++ b/include/Compiler/Command.h @@ -71,9 +71,9 @@ public: CompilationDatabase(CompilationDatabase&& other); - CompilationDatabase& operator= (const CompilationDatabase&) = delete; + CompilationDatabase& operator=(const CompilationDatabase&) = delete; - CompilationDatabase& operator= (CompilationDatabase&& other); + CompilationDatabase& operator=(CompilationDatabase&& other); ~CompilationDatabase(); diff --git a/include/Compiler/Compilation.h b/include/Compiler/Compilation.h index 73e9ff79..f608343d 100644 --- a/include/Compiler/Compilation.h +++ b/include/Compiler/Compilation.h @@ -1,12 +1,14 @@ #pragma once +#include "CompilationUnit.h" #include "Module.h" #include "Preamble.h" -#include "CompilationUnit.h" #include "Support/FileSystem.h" namespace clang { + class CodeCompleteConsumer; + } namespace clice { diff --git a/include/Compiler/CompilationUnit.h b/include/Compiler/CompilationUnit.h index 079cb66d..2fc82833 100644 --- a/include/Compiler/CompilationUnit.h +++ b/include/Compiler/CompilationUnit.h @@ -3,10 +3,11 @@ #include #include "Directive.h" -#include "Compiler/Diagnostic.h" -#include "AST/SymbolID.h" -#include "AST/SourceCode.h" #include "AST/Resolver.h" +#include "AST/SourceCode.h" +#include "AST/SymbolID.h" +#include "Compiler/Diagnostic.h" + #include "clang/Tooling/Syntax/Tokens.h" namespace clice { diff --git a/include/Compiler/Diagnostic.h b/include/Compiler/Diagnostic.h index 3cd90c0b..e7892c40 100644 --- a/include/Compiler/Diagnostic.h +++ b/include/Compiler/Diagnostic.h @@ -9,7 +9,9 @@ #include "clang/Basic/Diagnostic.h" namespace clang { + class DiagnosticConsumer; + } namespace clice { diff --git a/include/Compiler/Directive.h b/include/Compiler/Directive.h index 4b857db0..7b8eda64 100644 --- a/include/Compiler/Directive.h +++ b/include/Compiler/Directive.h @@ -1,8 +1,9 @@ #pragma once #include "AST/SourceCode.h" -#include "clang/Lex/MacroInfo.h" + #include "llvm/ADT/DenseMap.h" +#include "clang/Lex/MacroInfo.h" namespace clice { diff --git a/include/Compiler/Module.h b/include/Compiler/Module.h index cb563714..65754c86 100644 --- a/include/Compiler/Module.h +++ b/include/Compiler/Module.h @@ -1,8 +1,9 @@ #pragma once +#include #include #include -#include + #include "Support/Struct.h" namespace clice { diff --git a/include/Compiler/Preamble.h b/include/Compiler/Preamble.h index c48e7487..416d6ff4 100644 --- a/include/Compiler/Preamble.h +++ b/include/Compiler/Preamble.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include "llvm/ADT/StringRef.h" diff --git a/include/Compiler/Scan.h b/include/Compiler/Scan.h index c14f0901..10b2dcbf 100644 --- a/include/Compiler/Scan.h +++ b/include/Compiler/Scan.h @@ -2,9 +2,11 @@ #include #include -#include "llvm/ADT/StringRef.h" + #include "AST/SourceCode.h" +#include "llvm/ADT/StringRef.h" + namespace clice { struct Inclusion { diff --git a/include/Compiler/Tidy.h b/include/Compiler/Tidy.h index 64acc7c4..95781d8e 100644 --- a/include/Compiler/Tidy.h +++ b/include/Compiler/Tidy.h @@ -1,11 +1,13 @@ #pragma once -#include "llvm/ADT/StringRef.h" - #include +#include "llvm/ADT/StringRef.h" + namespace clang { + class CompilerInstance; + } namespace clice::tidy { diff --git a/include/Compiler/Toolchain.h b/include/Compiler/Toolchain.h index c6e3b0eb..72d226e1 100644 --- a/include/Compiler/Toolchain.h +++ b/include/Compiler/Toolchain.h @@ -1,8 +1,8 @@ #pragma once #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" namespace clice::toolchain { diff --git a/include/Feature/CodeCompletion.h b/include/Feature/CodeCompletion.h index a07cce44..54ff65e9 100644 --- a/include/Feature/CodeCompletion.h +++ b/include/Feature/CodeCompletion.h @@ -1,9 +1,10 @@ #pragma once -#include #include +#include #include "AST/SourceCode.h" + #include "llvm/ADT/StringRef.h" namespace clice { diff --git a/include/Feature/Formatting.h b/include/Feature/Formatting.h index d2445a7f..32cef9ef 100644 --- a/include/Feature/Formatting.h +++ b/include/Feature/Formatting.h @@ -2,6 +2,7 @@ #include "AST/SourceCode.h" #include "Protocol/Feature/Formatting.h" + #include "llvm/ADT/StringRef.h" namespace clice::feature { diff --git a/include/Feature/Hover.h b/include/Feature/Hover.h index 95955454..78e3569c 100644 --- a/include/Feature/Hover.h +++ b/include/Feature/Hover.h @@ -1,7 +1,7 @@ #pragma once -#include "AST/SymbolKind.h" #include "AST/SourceCode.h" +#include "AST/SymbolKind.h" #include "Index/Shared.h" namespace clice::config { diff --git a/include/Feature/InlayHint.h b/include/Feature/InlayHint.h index fb012f80..eb007c55 100644 --- a/include/Feature/InlayHint.h +++ b/include/Feature/InlayHint.h @@ -1,7 +1,7 @@ #pragma once -#include "AST/SymbolID.h" #include "AST/SourceCode.h" +#include "AST/SymbolID.h" #include "Index/Shared.h" #include "Support/JSON.h" diff --git a/include/Feature/Lookup.h b/include/Feature/Lookup.h index 778b062b..8ad88da1 100644 --- a/include/Feature/Lookup.h +++ b/include/Feature/Lookup.h @@ -1,8 +1,8 @@ #pragma once +#include "AST/SymbolKind.h" #include "Server/Protocol.h" #include "Support/Struct.h" -#include "AST/SymbolKind.h" namespace clice::proto { diff --git a/include/Feature/SemanticToken.h b/include/Feature/SemanticToken.h index 974290b0..737322b2 100644 --- a/include/Feature/SemanticToken.h +++ b/include/Feature/SemanticToken.h @@ -1,7 +1,7 @@ #pragma once -#include "AST/SymbolKind.h" #include "AST/SourceCode.h" +#include "AST/SymbolKind.h" #include "Index/Shared.h" namespace clice::config { diff --git a/include/Feature/SignatureHelp.h b/include/Feature/SignatureHelp.h index b7066d1f..8e8aa882 100644 --- a/include/Feature/SignatureHelp.h +++ b/include/Feature/SignatureHelp.h @@ -1,10 +1,11 @@ #pragma once -#include #include +#include + +#include "Protocol/Feature/SignatureHelp.h" #include "llvm/ADT/StringRef.h" -#include "Protocol/Feature/SignatureHelp.h" namespace clice { diff --git a/include/Index/IncludeGraph.h b/include/Index/IncludeGraph.h index 5cb5f105..9f191d25 100644 --- a/include/Index/IncludeGraph.h +++ b/include/Index/IncludeGraph.h @@ -1,11 +1,15 @@ #pragma once #include + #include "AST/SourceCode.h" + #include "llvm/ADT/DenseMap.h" namespace clice { + class CompilationUnit; + } namespace clice::index { @@ -20,7 +24,7 @@ struct IncludeLocation { /// The include location that introduces this file. std::uint32_t include = -1; - friend bool operator== (const IncludeLocation&, const IncludeLocation&) = default; + friend bool operator==(const IncludeLocation&, const IncludeLocation&) = default; }; struct IncludeGraph { diff --git a/include/Index/MergedIndex.h b/include/Index/MergedIndex.h index f1b28b98..ecddd9c2 100644 --- a/include/Index/MergedIndex.h +++ b/include/Index/MergedIndex.h @@ -1,6 +1,7 @@ #pragma once #include "TUIndex.h" + #include "llvm/Support/Allocator.h" #include "llvm/Support/MemoryBuffer.h" @@ -25,9 +26,9 @@ public: MergedIndex(MergedIndex&& other); - MergedIndex& operator= (const MergedIndex&) = delete; + MergedIndex& operator=(const MergedIndex&) = delete; - MergedIndex& operator= (MergedIndex&& other); + MergedIndex& operator=(MergedIndex&& other); ~MergedIndex(); @@ -68,7 +69,7 @@ public: /// Merge the index with given header context. void merge(this Self& self, std::uint32_t path_id, std::uint32_t include_id, FileIndex& index); - friend bool operator== (MergedIndex& lhs, MergedIndex& rhs); + friend bool operator==(MergedIndex& lhs, MergedIndex& rhs); private: /// The binary serialization data of index. If you load merged index diff --git a/include/Index/TUIndex.h b/include/Index/TUIndex.h index 21a1f374..cd93ba4e 100644 --- a/include/Index/TUIndex.h +++ b/include/Index/TUIndex.h @@ -1,10 +1,11 @@ #pragma once #include + #include "IncludeGraph.h" +#include "AST/RelationKind.h" #include "AST/SourceCode.h" #include "AST/SymbolKind.h" -#include "AST/RelationKind.h" #include "Support/Bitmap.h" namespace clice::index { @@ -37,7 +38,7 @@ struct Occurrence { /// SymbolHash target; - friend bool operator== (const Occurrence&, const Occurrence&) = default; + friend bool operator==(const Occurrence&, const Occurrence&) = default; }; struct FileIndex { @@ -56,7 +57,7 @@ struct Symbol { /// All files that referenced this symbol. Bitmap reference_files; - friend bool operator== (const Symbol&, const Symbol&) = default; + friend bool operator==(const Symbol&, const Symbol&) = default; }; using SymbolTable = llvm::DenseMap; diff --git a/include/Index/USR.h b/include/Index/USR.h index fa575a70..41289b34 100644 --- a/include/Index/USR.h +++ b/include/Index/USR.h @@ -1,7 +1,7 @@ #pragma once -#include "clang/AST/Decl.h" #include "llvm/ADT/SmallVector.h" +#include "clang/AST/Decl.h" namespace clice::index { diff --git a/include/Protocol/Basic.h b/include/Protocol/Basic.h index 6850f238..c0ee8ffa 100644 --- a/include/Protocol/Basic.h +++ b/include/Protocol/Basic.h @@ -1,10 +1,10 @@ #pragma once #include -#include -#include #include #include +#include +#include namespace clice::proto { @@ -59,7 +59,7 @@ struct Position { /// `PositionEncodingKind`. uinteger character; - constexpr friend bool operator== (const Position&, const Position&) = default; + constexpr friend bool operator==(const Position&, const Position&) = default; }; struct Range { @@ -69,7 +69,7 @@ struct Range { /// The range's end position. Position end; - constexpr friend bool operator== (const Range&, const Range&) = default; + constexpr friend bool operator==(const Range&, const Range&) = default; }; struct Location { diff --git a/include/Protocol/Lifecycle.h b/include/Protocol/Lifecycle.h index 5acbe805..6c8122d9 100644 --- a/include/Protocol/Lifecycle.h +++ b/include/Protocol/Lifecycle.h @@ -1,8 +1,8 @@ #pragma once #include "Basic.h" -#include "TextDocument.h" #include "Notebook.h" +#include "TextDocument.h" #include "Workspace.h" /// clice currently ignores all `dynamicRegistration` field in LSP specification. diff --git a/include/Protocol/TextDocument.h b/include/Protocol/TextDocument.h index ded90ede..b06621b5 100644 --- a/include/Protocol/TextDocument.h +++ b/include/Protocol/TextDocument.h @@ -3,25 +3,25 @@ #include "Basic.h" #include "Feature/CallHierarchy.h" #include "Feature/CodeAction.h" +#include "Feature/CodeCompletion.h" #include "Feature/CodeLens.h" -#include "Feature/Diagnostic.h" -#include "Feature/DocumentLink.h" #include "Feature/Declaration.h" #include "Feature/Definition.h" +#include "Feature/Diagnostic.h" +#include "Feature/DocumentHighlight.h" +#include "Feature/DocumentLink.h" +#include "Feature/DocumentSymbol.h" #include "Feature/FoldingRange.h" #include "Feature/Formatting.h" #include "Feature/Hover.h" +#include "Feature/Implementation.h" #include "Feature/InlayHint.h" #include "Feature/Reference.h" #include "Feature/Rename.h" #include "Feature/SemanticTokens.h" #include "Feature/SignatureHelp.h" -#include "Feature/Implementation.h" -#include "Feature/CodeCompletion.h" #include "Feature/TypeDefinition.h" #include "Feature/TypeHierarchy.h" -#include "Feature/DocumentSymbol.h" -#include "Feature/DocumentHighlight.h" namespace clice::proto { diff --git a/include/Server/Config.h b/include/Server/Config.h index d88919dc..59beca6e 100644 --- a/include/Server/Config.h +++ b/include/Server/Config.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" diff --git a/include/Server/Convert.h b/include/Server/Convert.h index c4eabd84..a1a30b03 100644 --- a/include/Server/Convert.h +++ b/include/Server/Convert.h @@ -1,9 +1,9 @@ #pragma once -#include "Protocol/Protocol.h" -#include "Feature/SemanticToken.h" -#include "Feature/CodeCompletion.h" #include "Compiler/Diagnostic.h" +#include "Feature/CodeCompletion.h" +#include "Feature/SemanticToken.h" +#include "Protocol/Protocol.h" #include "Support/FileSystem.h" #include "Support/JSON.h" diff --git a/include/Server/Indexer.h b/include/Server/Indexer.h index 7a029e11..eb1b591b 100644 --- a/include/Server/Indexer.h +++ b/include/Server/Indexer.h @@ -5,7 +5,6 @@ #include "Config.h" #include "Convert.h" - #include "Async/Async.h" #include "Compiler/Command.h" #include "Index/MergedIndex.h" diff --git a/include/Server/Server.h b/include/Server/Server.h index b1b8ea76..7910a93f 100644 --- a/include/Server/Server.h +++ b/include/Server/Server.h @@ -5,8 +5,8 @@ #include "Indexer.h" #include "Async/Async.h" #include "Compiler/Command.h" -#include "Compiler/Preamble.h" #include "Compiler/Diagnostic.h" +#include "Compiler/Preamble.h" #include "Feature/DocumentLink.h" #include "Protocol/Protocol.h" @@ -61,7 +61,7 @@ public: ActiveFileManager() : capability(DefaultMaxActiveFileNum) {} ActiveFileManager(const ActiveFileManager&) = delete; - ActiveFileManager& operator= (const ActiveFileManager&) = delete; + ActiveFileManager& operator=(const ActiveFileManager&) = delete; /// Set the maximum active file count and it will be clamped to [1, UnlimitedActiveFileNum]. void set_capability(size_t size) { diff --git a/include/Support/Binary.h b/include/Support/Binary.h index bd5eb153..9cb791b6 100644 --- a/include/Support/Binary.h +++ b/include/Support/Binary.h @@ -1,14 +1,14 @@ #pragma once -#include #include -#include #include +#include +#include #include "Enum.h" -#include "Struct.h" -#include "Format.h" #include "FixedString.h" +#include "Format.h" +#include "Struct.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -263,7 +263,7 @@ struct Proxy { }; } - auto operator[] (std::size_t index) const { + auto operator[](std::size_t index) const { return Proxy{base, &as_array()[index]}; } diff --git a/include/Support/Compare.h b/include/Support/Compare.h index 849a6419..c9c999fb 100644 --- a/include/Support/Compare.h +++ b/include/Support/Compare.h @@ -16,7 +16,7 @@ struct Equal { struct equal_t { template - constexpr static bool operator() (const LHS& lhs, const RHS& rhs) { + constexpr static bool operator()(const LHS& lhs, const RHS& rhs) { return Equal::equal(lhs, rhs); } }; @@ -68,7 +68,7 @@ struct Less { struct less_t { template - constexpr static bool operator() (const LHS& lhs, const RHS& rhs) { + constexpr static bool operator()(const LHS& lhs, const RHS& rhs) { return Less::less(lhs, rhs); } }; @@ -127,7 +127,7 @@ struct Less { struct less_equal_t { template - constexpr static bool operator() (const LHS& lhs, const RHS& rhs) { + constexpr static bool operator()(const LHS& lhs, const RHS& rhs) { return equal(lhs, rhs) || less(lhs, rhs); } }; diff --git a/include/Support/Doxygen.h b/include/Support/Doxygen.h index 0ed16df3..7c0b4d0c 100644 --- a/include/Support/Doxygen.h +++ b/include/Support/Doxygen.h @@ -1,11 +1,11 @@ #pragma once -#include #include +#include -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" namespace clice { diff --git a/include/Support/Enum.h b/include/Support/Enum.h index 11f693b3..b7e9cbf0 100644 --- a/include/Support/Enum.h +++ b/include/Support/Enum.h @@ -1,12 +1,12 @@ #pragma once -#include #include -#include -#include +#include #include -#include +#include #include +#include +#include #include "Support/TypeTraits.h" @@ -81,7 +81,7 @@ public: constexpr Enum(const Enum&) = default; - constexpr Enum& operator= (const Enum&) = default; + constexpr Enum& operator=(const Enum&) = default; /// Get the underlying value of the enum. constexpr underlying value() const { @@ -108,7 +108,7 @@ public: return m_Value != invalid(); } - constexpr friend bool operator== (Enum lhs, Enum rhs) = default; + constexpr friend bool operator==(Enum lhs, Enum rhs) = default; constexpr static auto& all() { return enum_table::table; @@ -165,7 +165,7 @@ public: constexpr Enum(const Enum&) = default; - constexpr Enum& operator= (const Enum&) = default; + constexpr Enum& operator=(const Enum&) = default; /// Get the underlying value of the enum. constexpr underlying value() const { @@ -203,30 +203,30 @@ public: return m_Value != 0; } - constexpr friend bool operator== (Enum lhs, Enum rhs) = default; + constexpr friend bool operator==(Enum lhs, Enum rhs) = default; template Kind> - constexpr Enum operator| (Kind kind) const { + constexpr Enum operator|(Kind kind) const { return Enum(m_Value | (1 << underlying_value(kind))); } template Kind> - constexpr Enum operator& (Kind kind) const { + constexpr Enum operator&(Kind kind) const { return Enum(m_Value & (1 << underlying_value(kind))); } - constexpr Enum operator& (Enum e) const { + constexpr Enum operator&(Enum e) const { return Enum(m_Value & e.value()); } template Kind> - constexpr Enum& operator|= (Kind kind) { + constexpr Enum& operator|=(Kind kind) { m_Value |= (1 << underlying_value(kind)); return *this; } template Kind> - constexpr Enum& operator&= (Kind kind) { + constexpr Enum& operator&=(Kind kind) { m_Value &= (1 << underlying_value(kind)); return *this; } @@ -282,7 +282,7 @@ public: constexpr Enum(const Enum&) = default; - constexpr friend bool operator== (Enum lhs, Enum rhs) = default; + constexpr friend bool operator==(Enum lhs, Enum rhs) = default; constexpr underlying value() const { return m_Value; diff --git a/include/Support/FileSystem.h b/include/Support/FileSystem.h index feeb45b0..009e71e0 100644 --- a/include/Support/FileSystem.h +++ b/include/Support/FileSystem.h @@ -3,11 +3,12 @@ #include #include "Assert.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/VirtualFileSystem.h" -#include "llvm/Support/MemoryBuffer.h" + #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" namespace clice { diff --git a/include/Support/FixedString.h b/include/Support/FixedString.h index 3abd4a1b..829c34d1 100644 --- a/include/Support/FixedString.h +++ b/include/Support/FixedString.h @@ -15,6 +15,13 @@ struct fixed_string : std::array { this->data()[N] = '\0'; } + constexpr fixed_string(const char* str) { + for(std::size_t i = 0; i < N; ++i) { + this->data()[i] = str[i]; + } + this->data()[N] = '\0'; + } + constexpr auto size() const { return N; } diff --git a/include/Support/Format.h b/include/Support/Format.h index e6ec79fd..4d8e8424 100644 --- a/include/Support/Format.h +++ b/include/Support/Format.h @@ -2,8 +2,10 @@ #include #include + #include "Support/JSON.h" #include "Support/Ranges.h" + #include "llvm/Support/Error.h" template <> diff --git a/include/Support/FuzzyMatcher.h b/include/Support/FuzzyMatcher.h index e9a02dfa..52920c14 100644 --- a/include/Support/FuzzyMatcher.h +++ b/include/Support/FuzzyMatcher.h @@ -1,6 +1,7 @@ #pragma once #include + #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" diff --git a/include/Support/GlobPattern.h b/include/Support/GlobPattern.h index 05daa029..29a6719e 100644 --- a/include/Support/GlobPattern.h +++ b/include/Support/GlobPattern.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/Support/Hash.h b/include/Support/Hash.h index acc3fc5a..aafb2a67 100644 --- a/include/Support/Hash.h +++ b/include/Support/Hash.h @@ -1,6 +1,7 @@ #pragma once #include "Struct.h" + #include "llvm/Support/HashBuilder.h" namespace clice::refl { diff --git a/include/Support/JSON.h b/include/Support/JSON.h index 8182793a..dffe70bf 100644 --- a/include/Support/JSON.h +++ b/include/Support/JSON.h @@ -1,14 +1,14 @@ #pragma once #include -#include #include #include +#include -#include "Ranges.h" -#include "TypeTraits.h" #include "Enum.h" +#include "Ranges.h" #include "Struct.h" +#include "TypeTraits.h" #include "llvm/Support/JSON.h" diff --git a/include/Support/Logging.h b/include/Support/Logging.h index d2b4400f..d8ebac8f 100644 --- a/include/Support/Logging.h +++ b/include/Support/Logging.h @@ -1,6 +1,7 @@ #pragma once #include "Format.h" + #include "spdlog/spdlog.h" namespace clice::logging { diff --git a/include/Support/ObjectPool.h b/include/Support/ObjectPool.h index 21c86cc6..29fb8977 100644 --- a/include/Support/ObjectPool.h +++ b/include/Support/ObjectPool.h @@ -1,7 +1,7 @@ #pragma once -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" namespace clice { @@ -18,9 +18,9 @@ public: StringSet(StringSet&&) = delete; - StringSet& operator= (const StringSet&) = delete; + StringSet& operator=(const StringSet&) = delete; - StringSet& operator= (StringSet&&) = delete; + StringSet& operator=(StringSet&&) = delete; ~StringSet() = default; @@ -72,7 +72,7 @@ struct object_ptr { explicit object_ptr(T* p) noexcept : ptr(p) {} - T& operator* () const noexcept { + T& operator*() const noexcept { return *ptr; } @@ -84,7 +84,7 @@ struct object_ptr { return ptr != nullptr; } - std::strong_ordering operator<=> (const object_ptr&) const = default; + std::strong_ordering operator<=>(const object_ptr&) const = default; }; template @@ -101,9 +101,9 @@ public: ObjectSet(ObjectSet&&) = delete; - ObjectSet& operator= (const ObjectSet&) = delete; + ObjectSet& operator=(const ObjectSet&) = delete; - ObjectSet& operator= (ObjectSet&&) = delete; + ObjectSet& operator=(ObjectSet&&) = delete; ~ObjectSet() { if constexpr(!std::is_trivially_destructible_v) { diff --git a/include/Support/Ranges.h b/include/Support/Ranges.h index 4b0949d0..cf44025d 100644 --- a/include/Support/Ranges.h +++ b/include/Support/Ranges.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include namespace clice { diff --git a/include/Support/Struct.h b/include/Support/Struct.h index 4fdac547..524dfe16 100644 --- a/include/Support/Struct.h +++ b/include/Support/Struct.h @@ -1,9 +1,9 @@ #pragma once -#include #include -#include #include +#include +#include #include "Support/TypeTraits.h" diff --git a/include/Support/StructedText.h b/include/Support/StructedText.h index 5b5d5594..153afbf5 100644 --- a/include/Support/StructedText.h +++ b/include/Support/StructedText.h @@ -76,7 +76,7 @@ public: StructedText(StructedText&&) = default; - StructedText& operator= (const StructedText& other) { + StructedText& operator=(const StructedText& other) { blocks.clear(); for(auto& b: other.blocks) { blocks.push_back(b->clone()); @@ -84,7 +84,7 @@ public: return *this; } - StructedText& operator= (StructedText&&) = default; + StructedText& operator=(StructedText&&) = default; void append(StructedText& doc); diff --git a/include/Test/Annotation.h b/include/Test/Annotation.h index ab44b33d..a948a1c3 100644 --- a/include/Test/Annotation.h +++ b/include/Test/Annotation.h @@ -1,8 +1,9 @@ #pragma once #include "AST/SourceCode.h" -#include "llvm/ADT/StringRef.h" + #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" namespace clice::testing { @@ -23,123 +24,7 @@ struct AnnotatedSource { /// /// A range annotation for 'key' creates both a `ranges["key"]` and an `offsets["key"]` /// (pointing to the start). - static AnnotatedSource from(llvm::StringRef content) { - std::string source; - source.reserve(content.size()); - - llvm::StringMap offsets; - llvm::StringMap ranges; - std::vector nameless_offsets; - - std::uint32_t offset = 0; - std::uint32_t i = 0; - - // Helper lambda to parse a point annotation $(key). - // It captures all necessary variables by reference. - // Returns true if a point was successfully parsed, false otherwise. - auto try_parse_point_annotation = [&]() -> bool { - if(content[i] != '$') { - return false; - } - - // Peek ahead to see if it's "$(key)" or just "$" - if(i + 1 < content.size() && content[i + 1] == '(') { - // It's the full "$(key)" syntax - uint32_t key_start = i + 2; - size_t key_end = content.find(')', key_start); - - if(key_end == llvm::StringRef::npos) { - return false; - } // Malformed - - llvm::StringRef key = content.slice(key_start, key_end); - /// empty key is regarded as a nameless, and `()` is not consumed. - if(key.empty()) { - // It's the shorthand "$" syntax for an nameless key - nameless_offsets.emplace_back(offset); - i += 1; // Advance cursor past the single '$' - } else { - offsets.try_emplace(key, offset); - i = key_end + 1; // Advance cursor past the entire "$(key)" - } - return true; - } else { - // It's the shorthand "$" syntax for an nameless key - nameless_offsets.emplace_back(offset); - i += 1; // Advance cursor past the single '$' - return true; - } - }; - - while(i < content.size()) { - // Check for a point annotation first. - if(try_parse_point_annotation()) { - continue; - } - - char c = content[i]; - - // Handle Range: @key[...] - if(c == '@') { - // Skip '@' - i += 1; - - const char open_bracket = '['; - const char close_bracket = ']'; - - llvm::StringRef key = content.substr(i).take_until( - [&](char c) { return isspace(c) || c == open_bracket; }); - i += key.size(); - - while(i < content.size() && isspace(content[i])) { - i++; - } - - assert(i < content.size() && content[i] == open_bracket && - "Expect @key[...] for ranges."); - i += 1; // Skip '[' - - uint32_t begin_offset = offset; - int bracket_level = 1; - - while(i < content.size() && bracket_level > 0) { - // Inside a range, we can still have nested point annotations. - if(try_parse_point_annotation()) { - continue; - } - - char inner_c = content[i]; - if(inner_c == open_bracket) - bracket_level++; - else if(inner_c == close_bracket) - bracket_level--; - - if(bracket_level > 0) { - source += inner_c; - offset += 1; - i += 1; - } else { - i += 1; // Skip the final ']' - } - } - - ranges.try_emplace(key, LocalSourceRange{begin_offset, offset}); - continue; - } - - // If nothing else matched, it's a regular character. - source += c; - offset += 1; - i += 1; - } - - return AnnotatedSource{ - std::move(source), - std::move(offsets), - std::move(ranges), - std::move(nameless_offsets), - }; - } + static AnnotatedSource from(llvm::StringRef content); }; struct AnnotatedSources { @@ -161,41 +46,7 @@ struct AnnotatedSources { /// #include "test.h" /// int x = foo(); /// ``` - void add_sources(llvm::StringRef content) { - std::string curr_file; - std::string curr_content; - - /// Save previous file to params. - auto save_previous_file = [&]() { - if(curr_file.empty()) { - return; - } - - add_source(curr_file, curr_content); - curr_file.clear(); - curr_content.clear(); - }; - - while(!content.empty()) { - llvm::StringRef line = content.take_front(content.find_first_of("\r\n")); - content = content.drop_front(line.size()); - if(content.starts_with("\r\n")) { - content = content.drop_front(2); - } else if(content.starts_with("\n")) { - content = content.drop_front(1); - } - - if(line.starts_with("#[") && line.ends_with("]")) { - save_previous_file(); - curr_file = line.slice(2, line.size() - 1).str(); - } else if(!curr_file.empty()) { - curr_content += line; - curr_content += '\n'; - } - } - - save_previous_file(); - } + void add_sources(llvm::StringRef content); }; } // namespace clice::testing diff --git a/include/Test/LocationChain.h b/include/Test/LocationChain.h deleted file mode 100644 index 5a59b3c7..00000000 --- a/include/Test/LocationChain.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace clice::testing { - -struct LocationChain { - /// All positions in the call chain, with the later - /// ones representing deeper inner levels. - std::vector locations; - - LocationChain(std::source_location current = std::source_location::current()) : - locations{current} {} - - LocationChain(LocationChain& outer, - std::source_location current = std::source_location::current()) : - locations{outer.locations} { - locations.emplace_back(current); - } - - LocationChain(const LocationChain&) = delete; - - /// Dump all locations. - void backtrace() { - for(auto location: locations) { - std::cout << location.file_name() << ":" << location.line() << ":" << location.column() - << "\n"; - } - } -}; - -} // namespace clice::testing diff --git a/include/Test/Platform.h b/include/Test/Platform.h index 0e489f30..e35ddf18 100644 --- a/include/Test/Platform.h +++ b/include/Test/Platform.h @@ -1,4 +1,3 @@ - namespace clice::testing { /// True if the target platform is Windows. @@ -48,4 +47,5 @@ constexpr inline bool CIEnvironment = true; #else constexpr inline bool CIEnvironment = false; #endif + } // namespace clice::testing diff --git a/include/Test/Runner.h b/include/Test/Runner.h new file mode 100644 index 00000000..d0afdb4e --- /dev/null +++ b/include/Test/Runner.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/StringRef.h" + +namespace clice::testing { + +enum class TestState { + Passed, + Skipped, + Failed, + Fatal, +}; + +struct TestAttrs { + bool skip = false; + bool focus = false; +}; + +struct TestCase { + std::string name; + std::string path; + std::size_t line; + TestAttrs attrs; + llvm::unique_function test; +}; + +struct TestSuite { + std::string name; + std::vector (*cases)(); +}; + +class Runner2 { +public: + static Runner2& instance(); + + void add_suite(std::string_view suite, std::vector (*cases)()); + + int run_tests(llvm::StringRef filter); + +private: + std::vector suites; +}; + +} // namespace clice::testing diff --git a/include/Test/TExpr.h b/include/Test/TExpr.h deleted file mode 100644 index 4c7ed908..00000000 --- a/include/Test/TExpr.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "Support/Compare.h" -#include "Support/Ranges.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/raw_ostream.h" - -namespace clice::testing { - -template -concept is_expr_v = requires { typename T::expr_tag; }; - -template -struct default_formatter : std::formatter { - using Base = std::formatter; - - template - auto format(const auto& value, FormatContext& ctx) const { - llvm::SmallString<256> buffer; - static_cast(this)->format_to(std::back_inserter(buffer), value); - return Base::format(std::string_view(buffer), ctx); - } -}; - -template -decltype(auto) compute(const Expr& expr) { - if constexpr(requires { typename Expr::expr_tag; }) { - return expr(); - } else { - return expr; - } -} - -} // namespace clice::testing - -#define BINARY_PREDICATE(name, op) \ - namespace clice::testing { \ - decltype(auto) name##_impl(auto&& lhs, auto&& rhs); \ - \ - template \ - struct name { \ - const LHS& lhs; \ - const RHS& rhs; \ - \ - using expr_tag = int; \ - \ - auto operator() () const { \ - return name##_impl(compute(lhs), compute(rhs)); \ - } \ - }; \ - \ - template \ - name(const LHS&, const RHS&) -> name; \ - } \ - \ - template \ - struct std::formatter> : \ - clice::testing::default_formatter>> { \ - void format_to(auto&& inserter, const auto& expr) const { \ - std::format_to(inserter, "{} " #op " {}", expr.lhs, expr.rhs); \ - } \ - }; \ - \ - decltype(auto) clice::testing::name##_impl(auto&& lhs, auto&& rhs) - -BINARY_PREDICATE(add, +) { - return lhs + rhs; -}; - -BINARY_PREDICATE(sub, -) { - return lhs - rhs; -} - -BINARY_PREDICATE(mul, *) { - return lhs * rhs; -} - -BINARY_PREDICATE(eq, ==) { - return refl::equal(lhs, rhs); -} - -BINARY_PREDICATE(ne, !=) { - return !refl::equal(lhs, rhs); -} - -BINARY_PREDICATE(lt, <) { - return refl::less(lhs, rhs); -} - -BINARY_PREDICATE(le, <=) { - return refl::less_equal(lhs, rhs); -} - -BINARY_PREDICATE(gt, >) { - return refl::less(rhs, lhs); -} - -BINARY_PREDICATE(ge, >=) { - return refl::less_equal(rhs, lhs); -} - -BINARY_PREDICATE(has, has) { - return ranges::contains(lhs, rhs); -} - -#undef BINARY_PREDICATE diff --git a/include/Test/Test.h b/include/Test/Test.h index 3339e23d..2f8a2d7b 100644 --- a/include/Test/Test.h +++ b/include/Test/Test.h @@ -1,179 +1,130 @@ #pragma once -#include "TExpr.h" +#include +#include +#include +#include + #include "Platform.h" -#include "LocationChain.h" -#include "Support/JSON.h" -#include "Support/Format.h" +#include "Runner.h" #include "Support/Compare.h" #include "Support/FileSystem.h" #include "Support/FixedString.h" + +#include "cpptrace/cpptrace.hpp" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/StringMap.h" namespace clice::testing { -struct may_failure; +template +struct TestSuiteDef { +private: + TestState state = TestState::Passed; -class Runner { public: - static Runner& instance(); + using Self = Derived; - using Suite = void (*)(); - using Test = llvm::unique_function; - - void add_suite(std::string_view name, Suite suite); - - void on_test(std::string_view name, Test test, bool skipped); - - /// Current test is failed, continue to execute the next test in the suite. - void fail(const may_failure& failure); - - bool fatal_error_occured() { - return curr_fatal; + void failure() { + state = TestState::Failed; } - /// Run all test suites. - int run_tests(); - -private: - Runner() = default; - Runner(const Runner&) = delete; - Runner(Runner&&) = delete; - -private: - bool curr_failed = false; - bool skipped = false; - bool curr_fatal = false; - - /// Whether all tests in this test suite are skipped. - bool all_skipped = true; - - std::string curr_suite_name; - std::uint32_t curr_tests_count = 0; - std::uint32_t curr_failed_tests_count = 0; - std::uint32_t total_tests_count = 0; - std::uint32_t total_suites_count = 0; - std::uint32_t total_failed_tests_count = 0; - std::chrono::milliseconds curr_test_duration; - std::chrono::milliseconds total_test_duration; - std::unordered_map> suites; -}; - -template -struct suite { - template - suite(Suite suite) { - static_assert(std::convertible_to, "Suite must be stateless!"); - Runner::instance().add_suite(suite_name, suite); - } -}; - -struct test { - test(std::string_view name) : name(name) {} - - template - void operator= (Test&& test) { - Runner::instance().on_test(name, std::forward(test), skipped); + void pass() { + state = TestState::Passed; } - bool skipped = false; - std::string name; -}; - -struct may_failure { - bool failed = false; - bool fatal = false; - std::string expression; - std::source_location location; - std::string message; - - may_failure& operator<< (std::string message) { - this->message += std::move(message); - return *this; + void skip() { + state = TestState::Skipped; } - ~may_failure() { - Runner::instance().fail(*this); + constexpr inline static auto& test_cases() { + static std::vector instance; + return instance; } -}; -constexpr inline struct { - template - may_failure operator() (const TExpr& expr, - std::source_location location = std::source_location::current()) const { - bool failed = false; - std::string expression = "false"; - std::string message; + constexpr inline static auto suites() { + return std::move(test_cases()); + } - if constexpr(is_expr_v) { - auto result = expr(); - if(!static_cast(result)) { - failed = true; + template + inline static bool _register_suites = [] { + Runner2::instance().add_suite(TestName.data(), &suites); + return true; + }(); - /// TODO: use pretty print, if the expression is too long. - expression = std::format("{}", expr); + template + inline static bool _register_test_case = [] { + auto run_test = +[] -> TestState { + Derived test; + if constexpr(requires { test.setup(); }) { + test.setup(); } - } else { - if(!static_cast(expr)) { - failed = true; - if constexpr(requires { expr.error(); }) { - message = std::format("{}", expr.error()); - } + (test.*test_body)(); + + if constexpr(requires { test.teardown(); }) { + test.teardown(); } - } - return may_failure{ - failed, - false, - std::move(expression), - location, - std::move(message), + return test.state; }; - } -} expect; -constexpr inline struct { - test&& operator/ (test&& test) const { - test.skipped = true; - return std::move(test); - } -} skip; - -struct skip_if { - bool condition; - - test&& operator/ (test&& test) const { - test.skipped = condition; - return std::move(test); - } + test_cases().emplace_back(case_name.data(), path.data(), line, attrs, run_test); + return true; + }(); }; -struct skip_unless { - bool condition; +inline void print_trace(cpptrace::stacktrace& trace, std::source_location location) { + auto& frames = trace.frames; + auto it = std::ranges::find_if(frames, [&](cpptrace::stacktrace_frame& frame) { + return frame.filename != location.file_name(); + }); + frames.erase(it, frames.end()); + trace.print(); +} - test&& operator/ (test&& test) const { - test.skipped = !condition; - return std::move(test); - } -}; +#define TEST_SUITE(name) struct name##TEST : TestSuiteDef<#name, name##TEST> -constexpr inline struct { - may_failure&& operator/ (may_failure&& failure) const { - if(failure.failed) { - failure.fatal = true; - } - return std::move(failure); - } -} fatal; +#define TEST_CASE(name, ...) \ + void _register_##name() { \ + constexpr auto file_name = std::source_location::current().file_name(); \ + constexpr auto file_len = std::string_view(file_name).size(); \ + (void)_register_suites<>; \ + (void)_register_test_case<#name, \ + &Self::test_##name, \ + fixed_string(file_name), \ + std::source_location::current().line() __VA_OPT__(, ) \ + __VA_ARGS__>; \ + } \ + void test_##name() -struct that_t { - template - constexpr decltype(auto) operator% (const TExpr& expr) const { - return expr; - } -}; +#define CLICE_CHECK_IMPL(condition, return_action) \ + do { \ + if(condition) [[unlikely]] { \ + auto trace = cpptrace::generate_trace(); \ + clice::testing::print_trace(trace, std::source_location::current()); \ + failure(); \ + return_action; \ + } \ + } while(0) -inline that_t that; +#define EXPECT_TRUE(expr) CLICE_CHECK_IMPL(!(expr), (void)0) +#define EXPECT_FALSE(expr) CLICE_CHECK_IMPL((expr), (void)0) +#define EXPECT_EQ(lhs, rhs) CLICE_CHECK_IMPL((lhs) != (rhs), (void)0) +#define EXPECT_NE(lhs, rhs) CLICE_CHECK_IMPL((lhs) == (rhs), (void)0) + +#define ASSERT_TRUE(expr) CLICE_CHECK_IMPL(!(expr), return) +#define ASSERT_FALSE(expr) CLICE_CHECK_IMPL((expr), return) +#define ASSERT_EQ(lhs, rhs) CLICE_CHECK_IMPL((lhs) != (rhs), return) +#define ASSERT_NE(lhs, rhs) CLICE_CHECK_IMPL((lhs) == (rhs), return) + +#define CO_ASSERT_TRUE(expr) CLICE_CHECK_IMPL(!(expr), co_return) +#define CO_ASSERT_FALSE(expr) CLICE_CHECK_IMPL((expr), co_return) +#define CO_ASSERT_EQ(lhs, rhs) CLICE_CHECK_IMPL((lhs) != (rhs), co_return) +#define CO_ASSERT_NE(lhs, rhs) CLICE_CHECK_IMPL((lhs) == (rhs), co_return) } // namespace clice::testing diff --git a/include/Test/Tester.h b/include/Test/Tester.h index 590f3304..c228a3a5 100644 --- a/include/Test/Tester.h +++ b/include/Test/Tester.h @@ -1,10 +1,10 @@ #pragma once -#include "Test.h" #include "Annotation.h" -#include "Protocol/Protocol.h" +#include "Test.h" #include "Compiler/Command.h" #include "Compiler/Compilation.h" +#include "Protocol/Protocol.h" #include "Support/Logging.h" namespace clice::testing { @@ -38,7 +38,7 @@ struct Tester { bool compile_with_pch(llvm::StringRef standard = "-std=c++20"); - std::uint32_t operator[] (llvm::StringRef file, llvm::StringRef pos) { + std::uint32_t operator[](llvm::StringRef file, llvm::StringRef pos) { return sources.all_files.lookup(file).offsets.lookup(pos); } diff --git a/src/AST/Resolver.cpp b/src/AST/Resolver.cpp index dae22fa7..6961bfa1 100644 --- a/src/AST/Resolver.cpp +++ b/src/AST/Resolver.cpp @@ -1,8 +1,10 @@ #include "AST/Resolver.h" + #include "Support/Format.h" + #include "clang/Sema/Template.h" -#include "clang/Sema/TreeTransform.h" #include "clang/Sema/TemplateDeduction.h" +#include "clang/Sema/TreeTransform.h" namespace clice { @@ -626,10 +628,14 @@ public: /// SomeAllocator -> SomeAllocator if(auto TST = Alloc->getAs()) { - llvm::SmallVector replaceArguments = {T}; + llvm::SmallVector replaceArguments = {T}; + llvm::SmallVector canonicalArguments; + for(auto& arg: replaceArguments) { + canonicalArguments.emplace_back(context.getCanonicalTemplateArgument(arg)); + } return context.getTemplateSpecializationType(TST->getTemplateName(), replaceArguments, - replaceArguments); + canonicalArguments); } } } diff --git a/src/AST/Selection.cpp b/src/AST/Selection.cpp index 5d8b817b..3a1ea0f6 100644 --- a/src/AST/Selection.cpp +++ b/src/AST/Selection.cpp @@ -1,10 +1,13 @@ +#include "AST/Selection.h" + +#include +#include #include #include -#include -#include -#include "AST/Selection.h" + #include "Compiler/CompilationUnit.h" #include "Support/Logging.h" + #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -193,7 +196,7 @@ public: private: struct range_less { - bool operator() (TokenRange L, TokenRange R) const { + bool operator()(TokenRange L, TokenRange R) const { return L.begin() < R.begin(); } }; diff --git a/src/AST/SymbolKind.cpp b/src/AST/SymbolKind.cpp index cdce32da..73104747 100644 --- a/src/AST/SymbolKind.cpp +++ b/src/AST/SymbolKind.cpp @@ -1,4 +1,5 @@ #include "AST/SymbolKind.h" + #include "Compiler/Compilation.h" namespace clice { diff --git a/src/AST/Utility.cpp b/src/AST/Utility.cpp index 532140b1..478e5026 100644 --- a/src/AST/Utility.cpp +++ b/src/AST/Utility.cpp @@ -1,18 +1,20 @@ #include "AST/Utility.h" + #include "Support/Format.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/ScopedPrinter.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceManager.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/SaveAndRestore.h" -#include "llvm/Support/ScopedPrinter.h" -#include "llvm/ADT/SmallSet.h" -#include "clang/AST/ASTDiagnostic.h" namespace clice::ast { @@ -98,7 +100,6 @@ const static clang::CXXRecordDecl* getDeclContextForTemplateInstationPattern(con const clang::NamedDecl* instantiated_from(const clang::NamedDecl* decl) { if(auto CTSD = llvm::dyn_cast(decl)) { - auto kind = CTSD->getTemplateSpecializationKind(); if(kind == clang::TSK_Undeclared) { /// The instantiation of template is lazy, in this case, the specialization is diff --git a/src/Async/Async.cpp b/src/Async/Async.cpp index f8f9f307..782a8a43 100644 --- a/src/Async/Async.cpp +++ b/src/Async/Async.cpp @@ -1,7 +1,7 @@ -#include - #include "Async/Async.h" +#include + namespace clice::async { /// The default event loop. diff --git a/src/Async/FileSystem.cpp b/src/Async/FileSystem.cpp index a63e52cf..5116a8f5 100644 --- a/src/Async/FileSystem.cpp +++ b/src/Async/FileSystem.cpp @@ -1,4 +1,5 @@ #include "Async/FileSystem.h" + #include "Support/Logging.h" namespace clice::async::awaiter {} diff --git a/src/Async/Network.cpp b/src/Async/Network.cpp index 621b4f7e..6b09228e 100644 --- a/src/Async/Network.cpp +++ b/src/Async/Network.cpp @@ -1,4 +1,5 @@ #include "Async/Network.h" + #include "Support/Logging.h" namespace clice::async::net { diff --git a/src/Compiler/Command.cpp b/src/Compiler/Command.cpp index 8ac73d52..00880cbf 100644 --- a/src/Compiler/Command.cpp +++ b/src/Compiler/Command.cpp @@ -1,11 +1,13 @@ #include "Compiler/Command.h" + +#include "Driver.h" #include "Compiler/Compilation.h" #include "Support/FileSystem.h" #include "Support/Logging.h" +#include "Support/ObjectPool.h" + #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/CommandLine.h" -#include "Driver.h" -#include "Support/ObjectPool.h" namespace clice { @@ -20,7 +22,7 @@ struct CompilationInfo { /// The canonical compilation arguments(input file and output file are removed). llvm::ArrayRef arguments; - friend bool operator== (const CompilationInfo&, const CompilationInfo&) = default; + friend bool operator==(const CompilationInfo&, const CompilationInfo&) = default; }; /// An item in the compilation database. @@ -40,12 +42,12 @@ struct JSONItem { /// get involved in equality judgement or hash computing. object_ptr next = {nullptr}; - friend bool operator== (const JSONItem& lhs, const JSONItem& rhs) { + friend bool operator==(const JSONItem& lhs, const JSONItem& rhs) { return lhs.json_src_path == rhs.json_src_path && lhs.file_path == rhs.file_path && lhs.info == rhs.info; } - friend bool operator< (const JSONItem& lhs, const JSONItem& rhs) { + friend bool operator<(const JSONItem& lhs, const JSONItem& rhs) { return std::tie(lhs.file_path, lhs.info) < std::tie(rhs.file_path, rhs.info); } }; @@ -564,7 +566,7 @@ CompilationDatabase::CompilationDatabase() : self(std::make_uniqueemplace_back(); diagnostic.id.value = raw_diagnostic.getID(); diff --git a/src/Compiler/Directive.cpp b/src/Compiler/Directive.cpp index eb3fc13e..7e7adfd3 100644 --- a/src/Compiler/Directive.cpp +++ b/src/Compiler/Directive.cpp @@ -1,6 +1,7 @@ #include "Compiler/Directive.h" -#include "clang/Lex/MacroInfo.h" + #include "clang/Lex/MacroArgs.h" +#include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" namespace clice { diff --git a/src/Compiler/Driver.h b/src/Compiler/Driver.h index 5476bfe9..63503bd1 100644 --- a/src/Compiler/Driver.h +++ b/src/Compiler/Driver.h @@ -2,10 +2,11 @@ #include "Compiler/Command.h" #include "Support/Logging.h" + #include "llvm/ADT/ScopeExit.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" -#include "llvm/Support/FileSystem.h" #include "clang/Driver/Driver.h" namespace clice { diff --git a/src/Compiler/Module.cpp b/src/Compiler/Module.cpp index 69b62cd8..ca0cb7de 100644 --- a/src/Compiler/Module.cpp +++ b/src/Compiler/Module.cpp @@ -1,5 +1,7 @@ #include "Compiler/Module.h" + #include "Compiler/Compilation.h" + #include "clang/Lex/Lexer.h" namespace clice { diff --git a/src/Compiler/Preamble.cpp b/src/Compiler/Preamble.cpp index d6eb36f4..e71aa39d 100644 --- a/src/Compiler/Preamble.cpp +++ b/src/Compiler/Preamble.cpp @@ -1,4 +1,5 @@ #include "Compiler/Preamble.h" + #include "AST/SourceCode.h" #include "Support/Format.h" #include "Support/Logging.h" diff --git a/src/Compiler/Tidy.cpp b/src/Compiler/Tidy.cpp index 10f1f2b8..cf70ca62 100644 --- a/src/Compiler/Tidy.cpp +++ b/src/Compiler/Tidy.cpp @@ -10,21 +10,23 @@ /// https://github.com/llvm/llvm-project//blob/0865ecc5150b9a55ba1f9e30b6d463a66ac362a6/clang-tools-extra/clangd/ParsedAST.cpp#L547 /// https://github.com/llvm/llvm-project//blob/0865ecc5150b9a55ba1f9e30b6d463a66ac362a6/clang-tools-extra/clangd/TidyProvider.cpp +#include "Compiler/Tidy.h" + #include "TidyImpl.h" #include "AST/Utility.h" #include "Compiler/Diagnostic.h" -#include "Compiler/Tidy.h" #include "Support/Logging.h" -#include "llvm/ADT/StringSet.h" + #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Process.h" #include "llvm/Support/StringSaver.h" #include "clang/Frontend/CompilerInstance.h" -#include "clang-tidy/ClangTidyOptions.h" #include "clang-tidy/ClangTidyCheck.h" -#include "clang-tidy/ClangTidyModuleRegistry.h" #include "clang-tidy/ClangTidyDiagnosticConsumer.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidyOptions.h" #define CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS #include "clang-tidy/ClangTidyForceLinker.h" @@ -201,7 +203,7 @@ public: } } - bool operator() (clang::diag::Group group_id) const { + bool operator()(clang::diag::Group group_id) const { return exceptions.contains(static_cast(group_id)) ? !default_enable : default_enable; } diff --git a/src/Compiler/TidyImpl.h b/src/Compiler/TidyImpl.h index 3dffa8d2..1255d89f 100644 --- a/src/Compiler/TidyImpl.h +++ b/src/Compiler/TidyImpl.h @@ -5,16 +5,15 @@ #include "Compiler/Diagnostic.h" #include "Compiler/Tidy.h" +#include "clang-tidy/ClangTidyCheck.h" #include "clang-tidy/ClangTidyModuleRegistry.h" #include "clang-tidy/ClangTidyOptions.h" -#include "clang-tidy/ClangTidyCheck.h" namespace clice::tidy { using namespace clang::tidy; class ClangTidyChecker { - public: /// The context of the clang-tidy checker. ClangTidyContext context; diff --git a/src/Compiler/Toolchain.cpp b/src/Compiler/Toolchain.cpp index 6a1cec11..c44064cd 100644 --- a/src/Compiler/Toolchain.cpp +++ b/src/Compiler/Toolchain.cpp @@ -1,16 +1,18 @@ #include "Compiler/Toolchain.h" + #include "Compiler/Command.h" #include "Support/FileSystem.h" #include "Support/Logging.h" + #include "llvm/ADT/ScopeExit.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" -#include "llvm/Support/FileSystem.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/Compilation.h" -#include "clang/Driver/Tool.h" -#include "llvm/Support/CommandLine.h" #include "llvm/TargetParser/Host.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Tool.h" #ifndef _WIN32 diff --git a/src/Feature/CodeCompletion.cpp b/src/Feature/CodeCompletion.cpp index edd18834..060b3a8b 100644 --- a/src/Feature/CodeCompletion.cpp +++ b/src/Feature/CodeCompletion.cpp @@ -1,12 +1,14 @@ -#include "AST/Utility.h" -#include "AST/SymbolKind.h" -#include "Compiler/Compilation.h" #include "Feature/CodeCompletion.h" + +#include "AST/SymbolKind.h" +#include "AST/Utility.h" +#include "Compiler/Compilation.h" #include "Support/FuzzyMatcher.h" + #include "clang/Basic/CharInfo.h" -#include "clang/Sema/Sema.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Sema.h" namespace clice::feature { diff --git a/src/Feature/Diagnostic.cpp b/src/Feature/Diagnostic.cpp index 5c11dcb4..f9fa9b7c 100644 --- a/src/Feature/Diagnostic.cpp +++ b/src/Feature/Diagnostic.cpp @@ -1,4 +1,5 @@ #include "Feature/Diagnostic.h" + #include "Compiler/CompilationUnit.h" #include "Server/Convert.h" #include "Support/Logging.h" diff --git a/src/Feature/DocumentLink.cpp b/src/Feature/DocumentLink.cpp index 76e792c1..1babe95d 100644 --- a/src/Feature/DocumentLink.cpp +++ b/src/Feature/DocumentLink.cpp @@ -1,7 +1,8 @@ -#include "Compiler/CompilationUnit.h" #include "Feature/DocumentLink.h" -#include "Support/Ranges.h" + +#include "Compiler/CompilationUnit.h" #include "Support/Compare.h" +#include "Support/Ranges.h" namespace clice::feature { diff --git a/src/Feature/DocumentSymbol.cpp b/src/Feature/DocumentSymbol.cpp index 32ce204f..dba76de4 100644 --- a/src/Feature/DocumentSymbol.cpp +++ b/src/Feature/DocumentSymbol.cpp @@ -1,9 +1,10 @@ +#include "Feature/DocumentSymbol.h" + #include "AST/FilterASTVisitor.h" #include "AST/Utility.h" #include "Compiler/Compilation.h" -#include "Feature/DocumentSymbol.h" -#include "Support/Ranges.h" #include "Support/Compare.h" +#include "Support/Ranges.h" namespace clice::feature { @@ -46,7 +47,6 @@ std::string symbol_detail(clang::ASTContext& Ctx, const clang::NamedDecl& ND) { /// Use DFS to traverse the AST and collect document symbols. class DocumentSymbolCollector : public FilteredASTVisitor { - public: using Base = FilteredASTVisitor; diff --git a/src/Feature/FoldingRange.cpp b/src/Feature/FoldingRange.cpp index 78cfe122..3766a39b 100644 --- a/src/Feature/FoldingRange.cpp +++ b/src/Feature/FoldingRange.cpp @@ -1,6 +1,7 @@ +#include "Feature/FoldingRange.h" + #include "AST/FilterASTVisitor.h" #include "Compiler/Compilation.h" -#include "Feature/FoldingRange.h" #include "Support/Compare.h" namespace clice::feature { @@ -253,7 +254,6 @@ private: /// Collect all condition macro's block as folding range. void collect_condition_directive(const std::vector& conds) { - // All condition directives have been stored in `conds` variable, ordered by presumed line // number increasement, so use a stack to handle the branch structure. llvm::SmallVector stack = {}; diff --git a/src/Feature/Formatting.cpp b/src/Feature/Formatting.cpp index e0778920..e9447ac5 100644 --- a/src/Feature/Formatting.cpp +++ b/src/Feature/Formatting.cpp @@ -1,6 +1,8 @@ #include "Feature/Formatting.h" -#include "Support/Logging.h" + #include "Server/Convert.h" +#include "Support/Logging.h" + #include "clang/Format/Format.h" namespace clice::feature { diff --git a/src/Feature/Hover.cpp b/src/Feature/Hover.cpp index e60631c1..80437859 100644 --- a/src/Feature/Hover.cpp +++ b/src/Feature/Hover.cpp @@ -1,3 +1,5 @@ +#include "Feature/Hover.h" + #include "AST/Selection.h" #include "AST/Semantic.h" #include "AST/Utility.h" @@ -5,7 +7,6 @@ #include "Index/Shared.h" #include "Support/Compare.h" #include "Support/Ranges.h" -#include "Feature/Hover.h" namespace clice::feature { diff --git a/src/Feature/InlayHint.cpp b/src/Feature/InlayHint.cpp index b944c7b8..cda300d6 100644 --- a/src/Feature/InlayHint.cpp +++ b/src/Feature/InlayHint.cpp @@ -1,10 +1,12 @@ -#include "AST/Utility.h" -#include "AST/FilterASTVisitor.h" #include "Feature/InlayHint.h" + +#include "AST/FilterASTVisitor.h" +#include "AST/Utility.h" #include "Support/Compare.h" #include "Support/Format.h" -#include "clang/Lex/Lexer.h" + #include "llvm/ADT/StringExtras.h" +#include "clang/Lex/Lexer.h" namespace clice::feature { diff --git a/src/Feature/SemanticToken.cpp b/src/Feature/SemanticToken.cpp index e2ae2d40..8ad4625b 100644 --- a/src/Feature/SemanticToken.cpp +++ b/src/Feature/SemanticToken.cpp @@ -1,8 +1,9 @@ +#include "Feature/SemanticToken.h" + #include "AST/Semantic.h" #include "Index/Shared.h" -#include "Support/Ranges.h" #include "Support/Compare.h" -#include "Feature/SemanticToken.h" +#include "Support/Ranges.h" namespace clice::feature { diff --git a/src/Feature/SignatureHelp.cpp b/src/Feature/SignatureHelp.cpp index ea11a219..bc9327ed 100644 --- a/src/Feature/SignatureHelp.cpp +++ b/src/Feature/SignatureHelp.cpp @@ -1,7 +1,9 @@ -#include "Compiler/Compilation.h" #include "Feature/SignatureHelp.h" -#include "clang/Sema/Sema.h" + +#include "Compiler/Compilation.h" + #include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Sema.h" namespace clice::feature { diff --git a/src/Index/IncludeGraph.cpp b/src/Index/IncludeGraph.cpp index 51b85344..6d9f9420 100644 --- a/src/Index/IncludeGraph.cpp +++ b/src/Index/IncludeGraph.cpp @@ -1,4 +1,5 @@ #include "Index/IncludeGraph.h" + #include "Compiler/CompilationUnit.h" namespace clice::index { diff --git a/src/Index/MergedIndex.cpp b/src/Index/MergedIndex.cpp index f4df581f..86037292 100644 --- a/src/Index/MergedIndex.cpp +++ b/src/Index/MergedIndex.cpp @@ -1,7 +1,9 @@ +#include "Index/MergedIndex.h" + #include "Serialization.h" #include "Support/Compare.h" #include "Support/FileSystem.h" -#include "Index/MergedIndex.h" + #include "llvm/ADT/DenseSet.h" #include "llvm/Support/raw_os_ostream.h" @@ -67,6 +69,7 @@ struct DenseMapInfo { lhs.target_symbol == rhs.target_symbol; } }; + } // namespace llvm namespace clice::index { @@ -76,7 +79,7 @@ struct IncludeContext { std::uint32_t canonical_id; - friend bool operator== (const IncludeContext&, const IncludeContext&) = default; + friend bool operator==(const IncludeContext&, const IncludeContext&) = default; }; struct HeaderContext { @@ -84,7 +87,7 @@ struct HeaderContext { llvm::SmallVector includes; - friend bool operator== (const HeaderContext&, const HeaderContext&) = default; + friend bool operator==(const HeaderContext&, const HeaderContext&) = default; }; struct CompilationContext { @@ -96,7 +99,7 @@ struct CompilationContext { std::vector include_locations; - friend bool operator== (const CompilationContext&, const CompilationContext&) = default; + friend bool operator==(const CompilationContext&, const CompilationContext&) = default; }; struct MergedIndex::Impl { @@ -164,7 +167,7 @@ struct MergedIndex::Impl { self.max_canonical_id += 1; } - friend bool operator== (const Impl&, const Impl&) = default; + friend bool operator==(const Impl&, const Impl&) = default; }; MergedIndex::MergedIndex(std::unique_ptr buffer, std::unique_ptr impl) : @@ -177,7 +180,7 @@ MergedIndex::MergedIndex(llvm::StringRef data) : MergedIndex::MergedIndex(MergedIndex&& other) = default; -MergedIndex& MergedIndex::operator= (MergedIndex&& other) = default; +MergedIndex& MergedIndex::operator=(MergedIndex&& other) = default; MergedIndex::~MergedIndex() = default; @@ -398,7 +401,6 @@ void MergedIndex::lookup(this const Self& self, SymbolHash symbol, RelationKind kind, llvm::function_ref callback) { - if(self.impl) { auto it = self.impl->relations.find(symbol); if(it == self.impl->relations.end()) [[unlikely]] { @@ -533,7 +535,7 @@ void MergedIndex::merge(this Self& self, }); } -bool operator== (MergedIndex& lhs, MergedIndex& rhs) { +bool operator==(MergedIndex& lhs, MergedIndex& rhs) { lhs.load_in_memory(); rhs.load_in_memory(); return *lhs.impl == *rhs.impl; diff --git a/src/Index/ProjectIndex.cpp b/src/Index/ProjectIndex.cpp index d40693d9..f4109b5f 100644 --- a/src/Index/ProjectIndex.cpp +++ b/src/Index/ProjectIndex.cpp @@ -1,5 +1,6 @@ -#include "Serialization.h" #include "Index/ProjectIndex.h" + +#include "Serialization.h" #include "Support/Ranges.h" namespace clice::index { diff --git a/src/Index/Serialization.h b/src/Index/Serialization.h index 4887de48..2ad68b10 100644 --- a/src/Index/Serialization.h +++ b/src/Index/Serialization.h @@ -1,8 +1,9 @@ #include "schema_generated.h" #include "Support/Bitmap.h" #include "Support/Ranges.h" -#include "llvm/ADT/StringRef.h" + #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" namespace clice::index { diff --git a/src/Index/TUIndex.cpp b/src/Index/TUIndex.cpp index 30278d95..aea7ef28 100644 --- a/src/Index/TUIndex.cpp +++ b/src/Index/TUIndex.cpp @@ -1,6 +1,8 @@ -#include "AST/Semantic.h" #include "Index/TUIndex.h" + +#include "AST/Semantic.h" #include "Support/Compare.h" + #include "llvm/Support/SHA256.h" namespace clice::index { diff --git a/src/Index/USRGeneration.cpp b/src/Index/USRGeneration.cpp index ef233646..a041f70f 100644 --- a/src/Index/USRGeneration.cpp +++ b/src/Index/USRGeneration.cpp @@ -1,4 +1,5 @@ #include "Index/USR.h" + #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -51,6 +52,7 @@ void AppendExprODRHash(const Expr* expr, llvm::raw_ostream& Out) { }; namespace { + class USRGenerator : public ConstDeclVisitor { SmallVectorImpl& Buf; llvm::raw_svector_ostream Out; @@ -139,6 +141,7 @@ public: /// the decl had no name. bool EmitDeclName(const NamedDecl* D); }; + } // end anonymous namespace //===----------------------------------------------------------------------===// diff --git a/src/Server/Config.cpp b/src/Server/Config.cpp index dbbc7a6a..6247afde 100644 --- a/src/Server/Config.cpp +++ b/src/Server/Config.cpp @@ -1,11 +1,12 @@ #define TOML_EXCEPTIONS 0 -#include "toml++/toml.hpp" - #include "Server/Config.h" + #include "Server/Version.h" +#include "Support/FileSystem.h" #include "Support/Logging.h" #include "Support/Ranges.h" -#include "Support/FileSystem.h" + +#include "toml++/toml.hpp" #include "llvm/ADT/StringMap.h" namespace clice::config { diff --git a/src/Server/Convert.cpp b/src/Server/Convert.cpp index adfda576..534b0fb6 100644 --- a/src/Server/Convert.cpp +++ b/src/Server/Convert.cpp @@ -1,8 +1,9 @@ #include "Server/Convert.h" + #include "Protocol/Protocol.h" -#include "Support/Ranges.h" -#include "Support/JSON.h" #include "Support/Format.h" +#include "Support/JSON.h" +#include "Support/Ranges.h" namespace clice::proto { diff --git a/src/Server/Document.cpp b/src/Server/Document.cpp index 11d4232d..b26f7a01 100644 --- a/src/Server/Document.cpp +++ b/src/Server/Document.cpp @@ -1,10 +1,11 @@ -#include "Support/Logging.h" -#include "Server/Server.h" #include "Compiler/Compilation.h" #include "Feature/Diagnostic.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileOutputBuffer.h" +#include "Server/Server.h" +#include "Support/Logging.h" + #include "llvm/ADT/ScopeExit.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/raw_ostream.h" namespace clice { diff --git a/src/Server/Feature.cpp b/src/Server/Feature.cpp index 0e20e65a..b8efafbe 100644 --- a/src/Server/Feature.cpp +++ b/src/Server/Feature.cpp @@ -1,15 +1,15 @@ -#include "Feature/Formatting.h" -#include "Server/Server.h" -#include "Server/Convert.h" #include "Compiler/Compilation.h" #include "Feature/CodeCompletion.h" -#include "Feature/Hover.h" -#include "Feature/SignatureHelp.h" #include "Feature/DocumentLink.h" #include "Feature/DocumentSymbol.h" #include "Feature/FoldingRange.h" -#include "Feature/SemanticToken.h" +#include "Feature/Formatting.h" +#include "Feature/Hover.h" #include "Feature/InlayHint.h" +#include "Feature/SemanticToken.h" +#include "Feature/SignatureHelp.h" +#include "Server/Convert.h" +#include "Server/Server.h" namespace clice { diff --git a/src/Server/Indexer.cpp b/src/Server/Indexer.cpp index 0b9e5dd1..cfd78340 100644 --- a/src/Server/Indexer.cpp +++ b/src/Server/Indexer.cpp @@ -1,6 +1,6 @@ +#include "Server/Indexer.h" #include "Compiler/Compilation.h" -#include "Server/Indexer.h" #include "Server/Convert.h" #include "Support/Compare.h" #include "Support/Logging.h" diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index 60268d10..451ba367 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -1,6 +1,7 @@ -#include "Support/Logging.h" #include "Server/Server.h" +#include "Support/Logging.h" + namespace clice { ActiveFileManager::ActiveFile& ActiveFileManager::lru_put_impl(llvm::StringRef path, diff --git a/src/Support/Doxygen.cpp b/src/Support/Doxygen.cpp index d7550524..cb3a9218 100644 --- a/src/Support/Doxygen.cpp +++ b/src/Support/Doxygen.cpp @@ -1,9 +1,11 @@ #include "Support/Doxygen.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/StringSwitch.h" + #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/raw_ostream.h" namespace clice { + void DoxygenInfo::add_block_command_comment(llvm::StringRef tag, llvm::StringRef content) { auto [it, _] = block_command_comments.try_emplace(tag); it->second.emplace_back(content.str()); @@ -246,4 +248,5 @@ std::pair strip_doxygen_info(llvm::StringRef raw_comme } return {di, os.str()}; } + } // namespace clice diff --git a/src/Support/FuzzyMatcher.cpp b/src/Support/FuzzyMatcher.cpp index 8a30ea86..bd2f89b7 100644 --- a/src/Support/FuzzyMatcher.cpp +++ b/src/Support/FuzzyMatcher.cpp @@ -48,6 +48,7 @@ //===----------------------------------------------------------------------===// #include "Support/FuzzyMatcher.h" + #include "llvm/Support/Format.h" namespace clice { diff --git a/src/Support/GlobPattern.cpp b/src/Support/GlobPattern.cpp index 7808cc11..533a04a5 100644 --- a/src/Support/GlobPattern.cpp +++ b/src/Support/GlobPattern.cpp @@ -1,7 +1,7 @@ -#include - #include "Support/GlobPattern.h" +#include + namespace clice { // Expands character ranges and returns a bitmap. @@ -363,7 +363,6 @@ bool GlobPattern::SubGlobPattern::match(llvm::StringRef str) const { }; while(current_glob_seg < seg_num) { - if(s == s_end) { // Return true if all pattern characters are processed or only // '*' or '/' characters remain diff --git a/src/Support/Logging.cpp b/src/Support/Logging.cpp index 2bfeac95..533877a0 100644 --- a/src/Support/Logging.cpp +++ b/src/Support/Logging.cpp @@ -1,10 +1,11 @@ #include "Support/Logging.h" + #include "Support/FileSystem.h" -#include "spdlog/sinks/stdout_sinks.h" -#include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/ringbuffer_sink.h" +#include "spdlog/sinks/stdout_color_sinks.h" +#include "spdlog/sinks/stdout_sinks.h" namespace clice::logging { diff --git a/tests/unit/AST/Resolver.cpp b/tests/unit/AST/Resolver.cpp deleted file mode 100644 index 6c8146f2..00000000 --- a/tests/unit/AST/Resolver.cpp +++ /dev/null @@ -1,476 +0,0 @@ -#include "Test/Tester.h" -#include "clang/AST/RecursiveASTVisitor.h" - -namespace clice::testing { - -namespace { - -struct InputFinder : clang::RecursiveASTVisitor { - CompilationUnit& unit; - clang::QualType input; - clang::QualType expect; - - using Base = clang::RecursiveASTVisitor; - - InputFinder(CompilationUnit& unit) : unit(unit) {} - - bool TraverseDecl(clang::Decl* decl) { - if(decl && (llvm::isa(decl) || - unit.file_id(decl->getLocation()) == unit.interested_file())) { - return Base::TraverseDecl(decl); - } - - return true; - } - - bool VisitTypedefNameDecl(const clang::TypedefNameDecl* decl) { - if(decl->getName() == "input") { - input = decl->getUnderlyingType(); - } - - if(decl->getName() == "expect") { - expect = decl->getUnderlyingType(); - } - - return true; - } -}; - -suite<"TemplateResolver"> suite = [] { - auto run = [](llvm::StringRef code) { - Tester tester; - tester.add_main("main.cpp", code); - tester.compile(); - - InputFinder finder(*tester.unit); - finder.TraverseAST(tester.unit->context()); - - auto input = tester.unit->resolver().resolve(finder.input); - auto target = finder.expect; - - expect(that % (!input.isNull())); - expect(that % (!target.isNull())); - expect(that % (input.getCanonicalType() == target.getCanonicalType())); - }; - - test("TypeParameterType") = [&] { - run(R"cpp( -template -struct A { - using type = T; -}; - -template -struct test { - using input = typename A::type; - using expect = X; -}; -)cpp"); - }; - - test("SingleLevel") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = type_list; -}; - -template -struct test { - using input = typename A::type; - using expect = type_list; -}; -)cpp"); - }; - - test("SingleLevelNotDependent") = [&] { - run(R"cpp( -template -struct A { - using type = int; -}; - -template -struct test { - using input = typename A::type; - using expect = int; -}; -)cpp"); - }; - - test("MultiLevel") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = type_list; -}; - -template -struct B { - using type = typename A::type; -}; - -template -struct C { - using type = typename B::type; -}; - -template -struct test { - using input = typename C::type; - using expect = type_list; -}; -)cpp"); - }; - - test("MultiLevelNotDependent") = [&] { - run(R"cpp( -template -struct A { - using type = int; -}; - -template -struct B { - using type = typename A::type; -}; - -template -struct C { - using type = typename B::type; -}; - -template -struct test { - using input = typename C::type; - using expect = int; -}; -)cpp"); - }; - - test("ArgumentDependent") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = T1; -}; - -template -struct B { - using type = type_list; -}; - -template -struct test { - using input = typename B::type>::type; - using expect = type_list; -}; -)cpp"); - }; - - test("AliasArgument") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = T1; -}; - -template -struct B { - using base = A; - using type = type_list; -}; - -template -struct test { - using input = typename B::type; - using expect = type_list; -}; -)cpp"); - }; - - test("AliasDependent") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = type_list; -}; - -template -struct B { - using base = A; - using type = typename base::type; -}; - -template -struct test { - using input = typename B::type; - using expect = type_list; -}; -)cpp"); - }; - - test("AliasTemplate") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = type_list; -}; - -template -struct B { - template - using type = typename A::type; -}; - -template -struct test { - using input = typename B::template type; - using expect = type_list; -}; -)cpp"); - }; - - test("BaseDependent") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = type_list; -}; - -template -struct B : A {}; - -template -struct test { - using input = typename B::type; - using expect = type_list; -}; -)cpp"); - }; - - test("MultiNested") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using self = A; - using type = type_list; -}; - -template -struct test { - using input = typename A::self::self::self::self::self::type; - using expect = type_list; -}; -)cpp"); - }; - - test("OuterDependentMemberClass") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - template - struct B { - template - struct C { - using type = type_list; - }; - }; -}; - -template -struct test { - using input = typename A::template B::template C::type; - using expect = type_list; -}; -)cpp"); - }; - - test("InnerDependentMemberClass") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct test { - template - struct B { - using type = type_list; - }; - - using input = typename B<1, T>::type; - using expect = type_list; -}; -)cpp"); - }; - - test("InnerDependentPartialMemberClass") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct test {}; - -template -struct test { - template - struct A { - using type = type_list; - }; - - using input = typename A<1, T>::type; - using expect = type_list; -}; -)cpp"); - }; - - test("PartialSpecialization") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A {}; - -template -struct B {}; - -template typename HKT> -struct B> { - using type = type_list; -}; - -template -struct test { - using input = typename B>::type; - using expect = type_list; -}; -)cpp"); - }; - - test("PartialDefaultArgument") = [&] { - run(R"cpp( -template -struct X {}; - -template -struct X { - using type = T; -}; - -template -struct test { - using input = typename X::type; - using expect = T; -}; -)cpp"); - }; - - test("DefaultArgument") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct A { - using type = type_list; -}; - -template > -struct B { - using type = typename U2::type; -}; - -template -struct test { - using input = typename B::type; - using expect = type_list; -}; -)cpp"); - }; - - test("PackExpansion") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct X { - using type = type_list; -}; - -template -struct test { - using input = typename X::type; - using expect = type_list; -}; -)cpp"); - }; - - test("BasePackExpansion") = [&] { - run(R"cpp( -template -struct type_list {}; - -template -struct X { - using type = type_list; -}; - -template -struct Y : X {}; - -template -struct test { - using input = typename Y::type; - using expect = type_list; -}; -)cpp"); - }; - - /// FIXME: headers not found - /// - /// test("Standard") = [&] { - /// run(R"cpp( - /// #include - /// - /// template - /// struct test { - /// using input = typename std::vector::reference; - /// using expect = T&; - /// }; - /// )cpp"); - /// }; -}; - -} // namespace - -} // namespace clice::testing diff --git a/tests/unit/AST/ResolverTests.cpp b/tests/unit/AST/ResolverTests.cpp new file mode 100644 index 00000000..83c6eb0b --- /dev/null +++ b/tests/unit/AST/ResolverTests.cpp @@ -0,0 +1,476 @@ +#include "Test/Test.h" +#include "Test/Tester.h" + +#include "clang/AST/RecursiveASTVisitor.h" + +namespace clice::testing { + +namespace { + +struct InputFinder : clang::RecursiveASTVisitor { + CompilationUnit& unit; + clang::QualType input; + clang::QualType expect; + + using Base = clang::RecursiveASTVisitor; + + InputFinder(CompilationUnit& unit) : unit(unit) {} + + bool TraverseDecl(clang::Decl* decl) { + if(decl && (llvm::isa(decl) || + unit.file_id(decl->getLocation()) == unit.interested_file())) { + Base::TraverseDecl(decl); + } + + return true; + } + + bool VisitTypedefNameDecl(const clang::TypedefNameDecl* decl) { + if(decl->getName() == "input") { + input = decl->getUnderlyingType(); + } + + if(decl->getName() == "expect") { + expect = decl->getUnderlyingType(); + } + + return true; + } +}; + +TEST_SUITE(TemplateResolver) { + +void run(llvm::StringRef code) { + Tester tester; + tester.add_main("main.cpp", code); + ASSERT_TRUE(tester.compile()); + + InputFinder finder(*tester.unit); + finder.TraverseAST(tester.unit->context()); + + auto input = tester.unit->resolver().resolve(finder.input); + auto target = finder.expect; + ASSERT_FALSE(input.isNull() || target.isNull()); + EXPECT_EQ(input.getCanonicalType(), target.getCanonicalType()); +} + +TEST_CASE(TypeParameterType) { + run(R"code( + template + struct A { + using type = T; + }; + + template + struct test { + using input = typename A::type; + using expect = X; + }; + )code"); +} + +TEST_CASE(SingleLevel) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = type_list; + }; + + template + struct test { + using input = typename A::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(SingleLevelNotDependent) { + run(R"code( + template + struct A { + using type = int; + }; + + template + struct test { + using input = typename A::type; + using expect = int; + }; + )code"); +} + +TEST_CASE(MultiLevel) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = type_list; + }; + + template + struct B { + using type = typename A::type; + }; + + template + struct C { + using type = typename B::type; + }; + + template + struct test { + using input = typename C::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(MultiLevelNotDependent) { + run(R"code( + template + struct A { + using type = int; + }; + + template + struct B { + using type = typename A::type; + }; + + template + struct C { + using type = typename B::type; + }; + + template + struct test { + using input = typename C::type; + using expect = int; + }; + )code"); +} + +TEST_CASE(ArgumentDependent) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = T1; + }; + + template + struct B { + using type = type_list; + }; + + template + struct test { + using input = typename B::type>::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(AliasArgument) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = T1; + }; + + template + struct B { + using base = A; + using type = type_list; + }; + + template + struct test { + using input = typename B::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(AliasDependent) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = type_list; + }; + + template + struct B { + using base = A; + using type = typename base::type; + }; + + template + struct test { + using input = typename B::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(AliasTemplate) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = type_list; + }; + + template + struct B { + template + using type = typename A::type; + }; + + template + struct test { + using input = typename B::template type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(BaseDependent) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = type_list; + }; + + template + struct B : A {}; + + template + struct test { + using input = typename B::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(MultiNested) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using self = A; + using type = type_list; + }; + + template + struct test { + using input = typename A::self::self::self::self::self::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(OuterDependentMemberClass) { + run(R"code( + template + struct type_list {}; + + template + struct A { + template + struct B { + template + struct C { + using type = type_list; + }; + }; + }; + + template + struct test { + using input = typename A::template B::template C::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(InnerDependentMemberClass) { + run(R"code( + template + struct type_list {}; + + template + struct test { + template + struct B { + using type = type_list; + }; + + using input = typename B<1, T>::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(InnerDependentPartialMemberClass) { + run(R"code( + template + struct type_list {}; + + template + struct test {}; + + template + struct test { + template + struct A { + using type = type_list; + }; + + using input = typename A<1, T>::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(PartialSpecialization) { + run(R"code( + template + struct type_list {}; + + template + struct A {}; + + template + struct B {}; + + template typename HKT> + struct B> { + using type = type_list; + }; + + template + struct test { + using input = typename B>::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(PartialDefaultArgument) { + run(R"code( + template + struct X {}; + + template + struct X { + using type = T; + }; + + template + struct test { + using input = typename X::type; + using expect = T; + }; + )code"); +} + +TEST_CASE(DefaultArgument) { + run(R"code( + template + struct type_list {}; + + template + struct A { + using type = type_list; + }; + + template > + struct B { + using type = typename U2::type; + }; + + template + struct test { + using input = typename B::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(PackExpansion) { + run(R"code( + template + struct type_list {}; + + template + struct X { + using type = type_list; + }; + + template + struct test { + using input = typename X::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(BasePackExpansion) { + run(R"code( + template + struct type_list {}; + + template + struct X { + using type = type_list; + }; + + template + struct Y : X {}; + + template + struct test { + using input = typename Y::type; + using expect = type_list; + }; + )code"); +} + +TEST_CASE(Standard) { + run(R"code( + #include + + template + struct test { + using input = typename std::vector::reference; + using expect = T&; + }; + )code"); +}; + +}; // TEST_SUITE(TemplateResolver) + +} // namespace + +} // namespace clice::testing diff --git a/tests/unit/AST/Selection.cpp b/tests/unit/AST/Selection.cpp deleted file mode 100644 index 8385696b..00000000 --- a/tests/unit/AST/Selection.cpp +++ /dev/null @@ -1,772 +0,0 @@ -#include "Test/Tester.h" -#include "AST/Selection.h" -#include "clang/Lex/Lexer.h" - -namespace clice { - -std::ostringstream& operator<< (std::ostringstream& os, const LocalSourceRange& range) { - os << range.begin << " - " << range.end; - return os; -} - -} // namespace clice - -namespace clice::testing { - -namespace { - -using namespace clang; - -static unsigned getTokenLengthAtLoc(SourceLocation Loc, - const SourceManager& SM, - const LangOptions& LangOpts) { - clang::Token TheTok; - if(clang::Lexer::getRawToken(Loc, TheTok, SM, LangOpts)) - return 0; - // FIXME: Here we check whether the token at the location is a greatergreater - // (>>) token and consider it as a single greater (>). This is to get it - // working for templates but it isn't correct for the right shift operator. We - // can avoid this by using half open char ranges in getFileRange() but getting - // token ending is not well supported in macroIDs. - if(TheTok.is(tok::greatergreater)) - return 1; - - return TheTok.getLength(); -} - -// Returns location of the starting of the token at a given EndLoc -static SourceLocation getLocForTokenBegin(SourceLocation EndLoc, - const SourceManager& SM, - const LangOptions& LangOpts) { - return EndLoc.getLocWithOffset(-(signed)getTokenLengthAtLoc(EndLoc, SM, LangOpts)); -} - -// Returns location of the last character of the token at a given loc -static SourceLocation getLocForTokenEnd(SourceLocation BeginLoc, - const SourceManager& SM, - const LangOptions& LangOpts) { - unsigned Len = getTokenLengthAtLoc(BeginLoc, SM, LangOpts); - return BeginLoc.getLocWithOffset(Len ? Len - 1 : 0); -} - -// Converts a char source range to a token range. -static SourceRange toTokenRange(CharSourceRange Range, - const SourceManager& SM, - const LangOptions& LangOpts) { - if(!Range.isTokenRange()) - Range.setEnd(getLocForTokenBegin(Range.getEnd(), SM, LangOpts)); - return Range.getAsRange(); -} - -// Returns the union of two token ranges. -// To find the maximum of the Ends of the ranges, we compare the location of the -// last character of the token. -static SourceRange unionTokenRange(SourceRange R1, - SourceRange R2, - const SourceManager& SM, - const LangOptions& LangOpts) { - SourceLocation Begin = - SM.isBeforeInTranslationUnit(R1.getBegin(), R2.getBegin()) ? R1.getBegin() : R2.getBegin(); - SourceLocation End = SM.isBeforeInTranslationUnit(getLocForTokenEnd(R1.getEnd(), SM, LangOpts), - getLocForTokenEnd(R2.getEnd(), SM, LangOpts)) - ? R2.getEnd() - : R1.getEnd(); - return SourceRange(Begin, End); -} - -bool isValidFileRange(const SourceManager& Mgr, SourceRange R) { - if(!R.getBegin().isValid() || !R.getEnd().isValid()) - return false; - - FileID BeginFID; - size_t BeginOffset = 0; - std::tie(BeginFID, BeginOffset) = Mgr.getDecomposedLoc(R.getBegin()); - - FileID EndFID; - size_t EndOffset = 0; - std::tie(EndFID, EndOffset) = Mgr.getDecomposedLoc(R.getEnd()); - - return BeginFID.isValid() && BeginFID == EndFID && BeginOffset <= EndOffset; -} - -SourceLocation includeHashLoc(FileID IncludedFile, const SourceManager& SM) { - assert(SM.getLocForEndOfFile(IncludedFile).isFileID()); - FileID IncludingFile; - unsigned Offset; - std::tie(IncludingFile, Offset) = SM.getDecomposedExpansionLoc(SM.getIncludeLoc(IncludedFile)); - bool Invalid = false; - llvm::StringRef Buf = SM.getBufferData(IncludingFile, &Invalid); - if(Invalid) - return SourceLocation(); - // Now buf is "...\n#include \n..." - // and Offset points here: ^ - // Rewind to the preceding # on the line. - assert(Offset < Buf.size()); - for(;; --Offset) { - if(Buf[Offset] == '#') - return SM.getComposedLoc(IncludingFile, Offset); - if(Buf[Offset] == '\n' || Offset == 0) // no hash, what's going on? - return SourceLocation(); - } -} - -// Given a range whose endpoints may be in different expansions or files, -// tries to find a range within a common file by following up the expansion and -// include location in each. -static SourceRange rangeInCommonFile(SourceRange R, - const SourceManager& SM, - const LangOptions& LangOpts) { - // Fast path for most common cases. - if(SM.isWrittenInSameFile(R.getBegin(), R.getEnd())) - return R; - // Record the stack of expansion locations for the beginning, keyed by FileID. - llvm::DenseMap BeginExpansions; - for(SourceLocation Begin = R.getBegin(); Begin.isValid(); - Begin = Begin.isFileID() ? includeHashLoc(SM.getFileID(Begin), SM) - : SM.getImmediateExpansionRange(Begin).getBegin()) { - BeginExpansions[SM.getFileID(Begin)] = Begin; - } - // Move up the stack of expansion locations for the end until we find the - // location in BeginExpansions with that has the same file id. - for(SourceLocation End = R.getEnd(); End.isValid(); - End = End.isFileID() - ? includeHashLoc(SM.getFileID(End), SM) - : toTokenRange(SM.getImmediateExpansionRange(End), SM, LangOpts).getEnd()) { - auto It = BeginExpansions.find(SM.getFileID(End)); - if(It != BeginExpansions.end()) { - if(SM.getFileOffset(It->second) > SM.getFileOffset(End)) - return SourceLocation(); - return {It->second, End}; - } - } - return SourceRange(); -} - -// Find an expansion range (not necessarily immediate) the ends of which are in -// the same file id. -static SourceRange getExpansionTokenRangeInSameFile(SourceLocation Loc, - const SourceManager& SM, - const LangOptions& LangOpts) { - return rangeInCommonFile(toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts), - SM, - LangOpts); -} - -// Returns the file range for a given Location as a Token Range -// This is quite similar to getFileLoc in SourceManager as both use -// getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs). -// However: -// - We want to maintain the full range information as we move from one file to -// the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange. -// - We want to split '>>' tokens as the lexer parses the '>>' in nested -// template instantiations as a '>>' instead of two '>'s. -// There is also getExpansionRange but it simply calls -// getImmediateExpansionRange on the begin and ends separately which is wrong. -static SourceRange getTokenFileRange(SourceLocation Loc, - const SourceManager& SM, - const LangOptions& LangOpts) { - SourceRange FileRange = Loc; - while(!FileRange.getBegin().isFileID()) { - if(SM.isMacroArgExpansion(FileRange.getBegin())) { - FileRange = unionTokenRange(SM.getImmediateSpellingLoc(FileRange.getBegin()), - SM.getImmediateSpellingLoc(FileRange.getEnd()), - SM, - LangOpts); - assert(SM.isWrittenInSameFile(FileRange.getBegin(), FileRange.getEnd())); - } else { - SourceRange ExpansionRangeForBegin = - getExpansionTokenRangeInSameFile(FileRange.getBegin(), SM, LangOpts); - SourceRange ExpansionRangeForEnd = - getExpansionTokenRangeInSameFile(FileRange.getEnd(), SM, LangOpts); - if(ExpansionRangeForBegin.isInvalid() || ExpansionRangeForEnd.isInvalid()) - return SourceRange(); - assert(SM.isWrittenInSameFile(ExpansionRangeForBegin.getBegin(), - ExpansionRangeForEnd.getBegin()) && - "Both Expansion ranges should be in same file."); - FileRange = unionTokenRange(ExpansionRangeForBegin, ExpansionRangeForEnd, SM, LangOpts); - } - } - return FileRange; -} - -std::optional toHalfOpenFileRange(const SourceManager& SM, - const LangOptions& LangOpts, - SourceRange R) { - SourceRange R1 = getTokenFileRange(R.getBegin(), SM, LangOpts); - if(!isValidFileRange(SM, R1)) - return std::nullopt; - - SourceRange R2 = getTokenFileRange(R.getEnd(), SM, LangOpts); - if(!isValidFileRange(SM, R2)) - return std::nullopt; - - SourceRange Result = rangeInCommonFile(unionTokenRange(R1, R2, SM, LangOpts), SM, LangOpts); - unsigned TokLen = getTokenLengthAtLoc(Result.getEnd(), SM, LangOpts); - // Convert from closed token range to half-open (char) range - Result.setEnd(Result.getEnd().getLocWithOffset(TokLen)); - if(!isValidFileRange(SM, Result)) - return std::nullopt; - - return Result; -} - -} // namespace - -suite<"SelectionTree"> selection = [] { - auto select_right = [](llvm::StringRef code, - auto&& callback, - std::source_location location = std::source_location::current()) { - Tester tester; - tester.add_main("main.cpp", code); - fatal / expect(that % tester.compile(), location); - /// expect(that % tester.unit->diagnostics().empty()); - - auto points = tester.nameless_points(); - expect(that % points.size() >= 1, location); - - LocalSourceRange selected_range; - selected_range.begin = points[0]; - selected_range.end = points.size() == 2 ? points[1] : points[0]; - auto tree = SelectionTree::create_right(*tester.unit, selected_range); - callback(tester, tree); - }; - - auto expect_select = [&](llvm::StringRef code, - const char* kind, - std::source_location location = std::source_location::current()) { - select_right( - code, - [&](Tester& tester, SelectionTree& tree) { - auto node = tree.common_ancestor(); - if(!kind) { - expect(that % !node, location); - } else { - expect(that % node, location); - auto range2 = toHalfOpenFileRange(tester.unit->context().getSourceManager(), - tester.unit->lang_options(), - node->source_range()); - LocalSourceRange range = { - tester.unit->file_offset(range2->getBegin()), - tester.unit->file_offset(range2->getEnd()), - }; - - /// llvm::outs() << tree << "\n"; - /// tree.print(llvm::outs(), *node, 2); - - expect(that % node->kind() == llvm::StringRef(kind), location); - expect(that % range == tester.range(), location); - } - }, - location); - }; - - test("Expressions") = [&] { - expect_select(R"( - struct AAA { struct BBB { static int ccc(); };}; - int x = @[AAA::BBB::c$c$c](); - )", - "DeclRefExpr"); - - expect_select(R"( - struct AAA { struct BBB { static int ccc(); };}; - int x = @[AAA::BBB::ccc($)]; - )", - "CallExpr"); - - expect_select(R"( - struct S { - int foo() const; - int bar() { return @[f$oo](); } - }; - )", - "MemberExpr"); - - expect_select(R"(void foo() { @[$foo](); })", "DeclRefExpr"); - expect_select(R"(void foo() { @[f$oo](); })", "DeclRefExpr"); - expect_select(R"(void foo() { @[fo$o](); })", "DeclRefExpr"); - - expect_select(R"(void foo() { @[foo$] (); })", "DeclRefExpr"); - - expect_select(R"(void foo() { @[foo$()]; })", "CallExpr"); - expect_select(R"(void foo() { @[foo$()]; /*comment*/$})", "CallExpr"); - expect_select(R"(const int x = 1, y = 2; int array[ @[$x] ][10][y];)", "DeclRefExpr"); - expect_select(R"(const int x = 1, y = 2; int array[x][10][ @[$y] ];)", "DeclRefExpr"); - expect_select(R"(void func(int x) { int v_array[ @[$x] ][10]; })", "DeclRefExpr"); - expect_select(R"( - int a; - decltype(@[$a] + a) b; - )", - "DeclRefExpr"); - - expect_select(R"( - void func() { @[__$func__]; } - )", - "PredefinedExpr"); - }; - - test("Literals") = [&] { - expect_select(R"( - auto lambda = [](const char*){ return 0; }; - int x = lambda(@["y$"]); - )", - "StringLiteral"); - - expect_select(R"(int x = @[42]$;)", "IntegerLiteral"); - expect_select(R"(const int x = 1, y = 2; int array[x][ @[$10] ][y];)", "IntegerLiteral"); - - expect_select(R"( - struct Foo{}; - Foo operator""_ud(unsigned long long); - Foo x = @[$12_ud]; - )", - "UserDefinedLiteral"); - }; - - test("ControlFlow") = [&] { - expect_select(R"( - void foo() { @[if (1$11) { return; } else {$ }]} } - )", - "IfStmt"); - - expect_select(R"(int bar; void foo() @[{ foo (); }]$)", "CompoundStmt"); - - /// FIXME: - /// expect_select(R"( - /// /*error-ok*/ - /// void func() @[{^])", - /// "CompoundStmt"); - - expect_select(R"( - struct Str { - const char *begin(); - const char *end(); - }; - Str makeStr(const char*); - void loop() { - for (const char C : @[mak$eStr("foo"$)]) - ; - } - )", - "CallExpr"); - }; - - test("Declarations") = [&] { - /// FIXME: how to handle this? - /// expect_select(R"( - /// #define TARGET void foo() - /// @[TAR$GET{ return; }] - /// )", - /// "FunctionDecl"); - - expect_select(R"(@[$void foo$()];)", "FunctionDecl"); - expect_select(R"(@[void $foo()];)", "FunctionDecl"); - - expect_select(R"( - struct S { S(const char*); }; - @[S s $= "foo"]; - )", - "VarDecl"); - - expect_select(R"( - struct S { S(const char*); }; - @[S $s = "foo"]; - )", - "VarDecl"); - - expect_select(R"( - @[void (*$S)(int) = nullptr]; - )", - "VarDecl"); - - expect_select(R"(@[int $a], b;)", "VarDecl"); - expect_select(R"(@[int a, $b];)", "VarDecl"); - expect_select(R"(@[struct {int x;} $y];)", "VarDecl"); - expect_select(R"(struct foo { @[int has$h<:32:>]; };)", "FieldDecl"); - expect_select(R"(struct {@[int $x];} y;)", "FieldDecl"); - - expect_select(R"( - void test(int bar) { - auto l = [ $@[foo = bar] ] { }; - })", - "VarDecl"); - }; - - test("Types") = [&] { - expect_select(R"( - struct AAA { struct BBB { static int ccc(); };}; - int x = AAA::@[B$B$B]::ccc(); - )", - "RecordTypeLoc"); - expect_select(R"( - struct AAA { struct BBB { static int ccc(); };}; - int x = AAA::@[B$BB$]::ccc(); - )", - "RecordTypeLoc"); - expect_select(R"( - struct Foo {}; - struct Bar : private @[Fo$o] {}; - )", - "RecordTypeLoc"); - expect_select(R"( - struct Foo {}; - struct Bar : @[Fo$o] {}; - )", - "RecordTypeLoc"); - expect_select(R"(@[$void] (*S)(int) = nullptr;)", "BuiltinTypeLoc"); - /// expect_select(R"(@[void (*S)$(int)] = nullptr;)", "FunctionProtoTypeLoc"); - expect_select(R"(@[void ($*S)(int)] = nullptr;)", "PointerTypeLoc"); - /// expect_select(R"(@[void $(*S)(int)] = nullptr;)", "ParenTypeLoc"); - expect_select(R"(@[$void] foo();)", "BuiltinTypeLoc"); - expect_select(R"(@[void foo$()];)", "FunctionProtoTypeLoc"); - expect_select(R"(const int x = 1, y = 2; @[i$nt] array[x][10][y];)", "BuiltinTypeLoc"); - expect_select(R"(int (*getFunc(@[do$uble]))(int);)", "BuiltinTypeLoc"); - expect_select(R"(class X{}; @[int X::$*]y[10];)", "MemberPointerTypeLoc"); - expect_select(R"(const @[a$uto] x = 42;)", "AutoTypeLoc"); - /// expect_select(R"(@[decltype$(1)] b;)", "DecltypeTypeLoc"); - expect_select(R"(@[de$cltype(a$uto)] a = 1;)", "AutoTypeLoc"); - expect_select(R"( - typedef int Foo; - enum Bar : @[Fo$o] {}; - )", - "TypedefTypeLoc"); - expect_select(R"( - typedef int Foo; - enum Bar : @[Fo$o]; - )", - "TypedefTypeLoc"); - }; - - test("CXXFeatures") = [&] { - expect_select(R"( - template - int x = @[T::$U::]ccc(); - )", - "NestedNameSpecifierLoc"); - expect_select(R"( - struct Foo {}; - struct Bar : @[v$ir$tual private Foo] {}; - )", - "CXXBaseSpecifier"); - expect_select(R"( - struct X { X(int); }; - class Y { - X x; - Y() : @[$x(4)] {} - }; - )", - "CXXCtorInitializer"); - expect_select(R"(@[st$ruct {int x;}] y;)", "CXXRecordDecl"); - expect_select(R"(struct foo { @[op$erator int()]; };)", "CXXConversionDecl"); - expect_select(R"(struct foo { @[$~foo()]; };)", "CXXDestructorDecl"); - expect_select(R"(struct foo { @[~$foo()]; };)", "CXXDestructorDecl"); - expect_select(R"(struct foo { @[fo$o(){}] };)", "CXXConstructorDecl"); - expect_select(R"( - struct S1 { void f(); }; - struct S2 { S1 * operator->(); }; - void test(S2 s2) { - s2@[-$>]f(); - } - )", - "DeclRefExpr"); // Test for overloaded operator-> - }; - - test("UsingEnum") = [&] { - expect_select(R"( - namespace ns { enum class A {}; }; - using enum ns::@[$A]; - )", - "EnumTypeLoc"); - expect_select(R"( - namespace ns { enum class A {}; using B = A; }; - using enum ns::@[$B]; - )", - "TypedefTypeLoc"); - expect_select(R"( - namespace ns { enum class A {}; }; - using enum @[$ns::]A; - )", - "NestedNameSpecifierLoc"); - expect_select(R"( - namespace ns { enum class A {}; }; - @[using $enum ns::A]; - )", - "UsingEnumDecl"); - expect_select(R"( - namespace ns { enum class A {}; }; - @[$using enum ns::A]; - )", - "UsingEnumDecl"); - }; - - test("Templates") = [&] { - expect_select(R"(template void foo(@[T*$...]x);)", "PackExpansionTypeLoc"); - expect_select(R"(template void foo(@[$T]*...x);)", - "TemplateTypeParmTypeLoc"); - expect_select(R"(template void foo() { @[$T] t; })", - "TemplateTypeParmTypeLoc"); - expect_select(R"( - template struct Foo {}; - template <@[template class /*cursor here*/$U]> - struct Foo*> {}; - )", - "TemplateTemplateParmDecl"); - expect_select(R"(template struct foo { ~foo<@[$T]>(){} };)", - "TemplateTypeParmTypeLoc"); - expect_select(R"( - template class Vector {}; - template