diff --git a/.clangd b/.clangd deleted file mode 100644 index ba4cbb36..00000000 --- a/.clangd +++ /dev/null @@ -1,2 +0,0 @@ -Diagnostics: - UnusedIncludes: None diff --git a/.github/workflows/publish-clice.yml b/.github/workflows/publish-clice.yml index 622b96fa..f8c319f3 100644 --- a/.github/workflows/publish-clice.yml +++ b/.github/workflows/publish-clice.yml @@ -46,7 +46,7 @@ jobs: - uses: ./.github/actions/setup-pixi with: - environments: develop + environments: package - name: Remove ci llvm toolchain on Windows if: runner.os == 'Windows' diff --git a/.github/workflows/test-cmake.yml b/.github/workflows/test-cmake.yml index c51d6aaf..92877402 100644 --- a/.github/workflows/test-cmake.yml +++ b/.github/workflows/test-cmake.yml @@ -21,8 +21,6 @@ jobs: uses: actions/checkout@v4 - uses: ./.github/actions/setup-pixi - with: - environments: develop - name: Build run: pixi run build ${{ matrix.build_type }} ON diff --git a/.github/workflows/test-xmake.yml b/.github/workflows/test-xmake.yml index f5064c39..1a0427f3 100644 --- a/.github/workflows/test-xmake.yml +++ b/.github/workflows/test-xmake.yml @@ -30,8 +30,6 @@ jobs: build-cache-key: ${{ matrix.os }}-${{ matrix.build_type }} - uses: ./.github/actions/setup-pixi - with: - environments: develop - name: Build run: pixi run xmake ${{ matrix.build_type }} diff --git a/.gitignore b/.gitignore index 8a8c67b2..1caf2a78 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ tests/unit/Local/ .vs/ .idea/ .claude +.clangd # pixi environments .env diff --git a/docs/en/dev/build.md b/docs/en/dev/build.md index ba1a037e..e561f094 100644 --- a/docs/en/dev/build.md +++ b/docs/en/dev/build.md @@ -30,7 +30,7 @@ pixi run integration-test Debug ``` > [!TIP] -> If you want to develop directly with `cmake`, `ninja`, `clang++`, etc., run `pixi shell -e develop` to enter a shell with all env vars configured. +> If you want to develop directly with `cmake`, `ninja`, `clang++`, etc., run `pixi shell` to enter a shell with all env vars configured. ### XMake diff --git a/docs/zh/dev/build.md b/docs/zh/dev/build.md index b46d3abd..48e3eb65 100644 --- a/docs/zh/dev/build.md +++ b/docs/zh/dev/build.md @@ -30,7 +30,7 @@ pixi run integration-test Debug ``` > [!TIP] -> 如果你想直接使用 `cmake`, `ninja`, `clang++` 等命令进行开发,请运行 `pixi shell -e develop` 进入已配置好环境变量的终端 +> 如果你想直接使用 `cmake`, `ninja`, `clang++` 等命令进行开发,请运行 `pixi shell` 进入已配置好环境变量的终端 ### XMake diff --git a/include/AST/FilterASTVisitor.h b/include/AST/FilterASTVisitor.h index 7c036002..ea45b142 100644 --- a/include/AST/FilterASTVisitor.h +++ b/include/AST/FilterASTVisitor.h @@ -14,7 +14,7 @@ class FilteredASTVisitor : public clang::RecursiveASTVisitor { public: using Base = clang::RecursiveASTVisitor; - FilteredASTVisitor(CompilationUnit& unit, bool interested_only) : + FilteredASTVisitor(CompilationUnitRef unit, bool interested_only) : unit(unit), interested_only(interested_only) {} #define CHECK_DERIVED_IMPL(func) \ @@ -181,7 +181,7 @@ public: #undef CHECK_DERIVED_IMPL protected: - CompilationUnit& unit; + CompilationUnitRef unit; bool interested_only; }; diff --git a/include/AST/Selection.h b/include/AST/Selection.h index 39b34127..d7ead6f7 100644 --- a/include/AST/Selection.h +++ b/include/AST/Selection.h @@ -11,7 +11,7 @@ namespace clice { -class CompilationUnit; +class CompilationUnitRef; /// A selection can partially or completely cover several AST nodes. /// The SelectionTree contains nodes that are covered, and their parents. @@ -47,7 +47,7 @@ public: /// - Func should return true on success (stop) and false on failure (continue) /// /// Always yields at least one tree. If no tokens are touched, it is empty. - static bool create_each(CompilationUnit& unit, + static bool create_each(CompilationUnitRef unit, LocalSourceRange range, llvm::function_ref callback); @@ -55,7 +55,7 @@ public: /// /// Where ambiguous (range is empty and borders two tokens), prefer the token /// on the right. - static SelectionTree create_right(CompilationUnit& unit, LocalSourceRange range); + static SelectionTree create_right(CompilationUnitRef unit, LocalSourceRange range); /// Copies are no good - contain pointers to other nodes. SelectionTree(const SelectionTree&) = delete; @@ -139,7 +139,7 @@ public: private: // Creates a selection tree for the given range in the main file. // The range includes bytes [Start, End). - SelectionTree(CompilationUnit& unit, LocalSourceRange range); + SelectionTree(CompilationUnitRef unit, LocalSourceRange range); // Stable-pointer storage, FIXME: use memory pool instead? std::deque nodes; diff --git a/include/AST/Semantic.h b/include/AST/Semantic.h index 12cbf943..9393bff5 100644 --- a/include/AST/Semantic.h +++ b/include/AST/Semantic.h @@ -13,7 +13,7 @@ class SemanticVisitor : public FilteredASTVisitor> { public: using Base = FilteredASTVisitor; - SemanticVisitor(CompilationUnit& unit, bool interested_only) : + SemanticVisitor(CompilationUnitRef unit, bool interested_only) : Base(unit, interested_only), unit(unit), resolver(unit.resolver()) {} public: @@ -725,7 +725,7 @@ public: } protected: - CompilationUnit& unit; + CompilationUnitRef unit; TemplateResolver& resolver; llvm::SmallVector decls; }; diff --git a/include/AST/SourceCode.h b/include/AST/SourceCode.h index 771fc832..a07e9ef6 100644 --- a/include/AST/SourceCode.h +++ b/include/AST/SourceCode.h @@ -110,7 +110,7 @@ struct Token { return is_at_start_of_line && kind == clang::tok::hash; } - /// The tokens after the include diretive are regarded as + /// The tokens after the include directive are regarded as /// a whole token, whose kind is `header_name`. For example /// `` and `"test.h"` are both header name. bool is_header_name() const { diff --git a/include/Compiler/Compilation.h b/include/Compiler/Compilation.h index f608343d..86bed0f3 100644 --- a/include/Compiler/Compilation.h +++ b/include/Compiler/Compilation.h @@ -15,7 +15,7 @@ namespace clice { struct CompilationParams { /// The kind of this compilation. - CompilationUnit::Kind kind; + CompilationKind kind; /// Whether to run clang-tidy. bool clang_tidy = false; @@ -48,9 +48,6 @@ struct CompilationParams { /// to cancel old compilation task. std::shared_ptr stop = std::make_shared(false); - /// Store all compilation errors in the process. - std::shared_ptr> diagnostics; - void add_remapped_file(llvm::StringRef path, llvm::StringRef content, std::uint32_t bound = -1) { @@ -62,23 +59,21 @@ struct CompilationParams { } }; -using CompilationResult = std::expected; - /// Only preprocess ths source flie. -CompilationResult preprocess(CompilationParams& params); +CompilationUnit preprocess(CompilationParams& params); /// Build AST from given file path and content. If pch or pcm provided, apply them to the compiler. /// Note this function will not check whether we need to update the PCH or PCM, caller should check /// their reusability and update in time. -CompilationResult compile(CompilationParams& params); +CompilationUnit compile(CompilationParams& params); /// Build PCH from given file path and content. -CompilationResult compile(CompilationParams& params, PCHInfo& out); +CompilationUnit compile(CompilationParams& params, PCHInfo& out); /// Build PCM from given file path and content. -CompilationResult compile(CompilationParams& params, PCMInfo& out); +CompilationUnit compile(CompilationParams& params, PCMInfo& out); /// Run code completion at the given location. -CompilationResult complete(CompilationParams& params, clang::CodeCompleteConsumer* consumer); +CompilationUnit complete(CompilationParams& params, clang::CodeCompleteConsumer* consumer); } // namespace clice diff --git a/include/Compiler/CompilationUnit.h b/include/Compiler/CompilationUnit.h index 2fc82833..8187c624 100644 --- a/include/Compiler/CompilationUnit.h +++ b/include/Compiler/CompilationUnit.h @@ -12,45 +12,71 @@ namespace clice { -/// All AST related information needed for language server. -class CompilationUnit { +enum class CompilationKind : std::uint8_t { + /// From preprocessing the source file. Therefore directives + /// are available but AST nodes are not. + Preprocess, + + /// From indexing the static source file. + Indexing, + + /// From building preamble for the source file. + Preamble, + + /// From building precompiled module for the module interface unit. + ModuleInterface, + + /// From building normal AST for source file(except preamble), interested file and top level + /// declarations are available. + Content, + + /// From running code completion for the source file(preamble is applied). + Completion, +}; + +enum class CompilationStatus : std::uint8_t { + Completed, + Cancelled, + SetupFail, + FatalError, +}; + +class CompilationUnitRef { public: - /// The kind describes how we preprocess this source file - /// to get this compilation unit. - enum class Kind : std::uint8_t { - /// From preprocessing the source file. Therefore directives - /// are available but AST nodes are not. - Preprocess, + struct Self; - /// From indexing the static source file. - Indexing, + CompilationUnitRef(Self* self) : self(self) {} - /// From building preamble for the source file. - Preamble, - - /// From building precompiled module for the module interface unit. - ModuleInterface, - - /// From building normal AST for source file(except preamble), interested file and top level - /// declarations are available. - Content, - - /// From running code completion for the source file(preamble is applied). - Completion, - }; - - using enum Kind; - struct Impl; - - CompilationUnit(Kind kind, Impl* impl) : kind(kind), impl(impl) {} - - CompilationUnit(const CompilationUnit&) = delete; - - CompilationUnit(CompilationUnit&& other) : kind(other.kind), impl(other.impl) { - other.impl = nullptr; + Self* operator->() { + return self; } - ~CompilationUnit(); +public: + CompilationKind kind(); + + CompilationStatus status(); + + /// Parse finished; ASTContext is usable but diagnostics may still contain errors. + bool completed() { + return status() == CompilationStatus::Completed; + } + + /// Compilation was cancelled; consumers should not touch any state. + bool cancelled() { + return status() == CompilationStatus::Cancelled; + } + + /// Failed during initial setup; diagnostics exist (location-free), ASTContext + /// is unavailable. + bool setup_fail() { + return status() == CompilationStatus::SetupFail; + } + + /// Hit an unrecoverable error; diagnostics and decoded source locations + /// are usable, other states are not unavailable. + bool fatal_error() { + return status() == CompilationStatus::FatalError; + } public: /// Get the file id for given file. If such file doesn't exist, the result @@ -165,7 +191,7 @@ public: bool is_module_interface_unit(); /// Return all diagnostics in the process of compilation. - auto diagnostics() -> llvm::ArrayRef; + auto diagnostics() -> std::vector&; auto top_level_decls() -> llvm::ArrayRef; @@ -196,10 +222,22 @@ public: /// Get symbol ID for given marco. index::SymbolID getSymbolID(const clang::MacroInfo* macro); -private: - Kind kind; +protected: + Self* self; +}; - Impl* impl; +/// All AST related information needed for language server. +class CompilationUnit : public CompilationUnitRef { +public: + explicit CompilationUnit(Self* impl) : CompilationUnitRef(impl) {} + + CompilationUnit(const CompilationUnit&) = delete; + + CompilationUnit(CompilationUnit&& other) : CompilationUnitRef(other.self) { + other.self = nullptr; + } + + ~CompilationUnit(); }; } // namespace clice diff --git a/include/Compiler/Diagnostic.h b/include/Compiler/Diagnostic.h index e7892c40..400bccbf 100644 --- a/include/Compiler/Diagnostic.h +++ b/include/Compiler/Diagnostic.h @@ -4,15 +4,6 @@ #include #include "AST/SourceCode.h" -#include "Compiler/Tidy.h" - -#include "clang/Basic/Diagnostic.h" - -namespace clang { - -class DiagnosticConsumer; - -} namespace clice { @@ -58,11 +49,6 @@ struct DiagnosticID { bool is_unused() const; }; -class DiagnosticCollector : public clang::DiagnosticConsumer { -public: - tidy::ClangTidyChecker* checker = nullptr; -}; - struct Diagnostic { /// The diagnostic id. DiagnosticID id; @@ -76,9 +62,6 @@ struct Diagnostic { /// The error message of this diagnostic. std::string message; - - static std::unique_ptr - create(std::shared_ptr> diagnostics); }; } // namespace clice diff --git a/include/Compiler/Directive.h b/include/Compiler/Directive.h index 7b8eda64..62b63a80 100644 --- a/include/Compiler/Directive.h +++ b/include/Compiler/Directive.h @@ -135,10 +135,6 @@ struct Directive { std::vector macros; std::vector pragmas; std::vector imports; - - /// Tell preprocessor to collect directives information and store them in `directives`. - static void attach(clang::Preprocessor& pp, - llvm::DenseMap& directives); }; } // namespace clice diff --git a/include/Compiler/Tidy.h b/include/Compiler/Tidy.h deleted file mode 100644 index 95781d8e..00000000 --- a/include/Compiler/Tidy.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include "llvm/ADT/StringRef.h" - -namespace clang { - -class CompilerInstance; - -} - -namespace clice::tidy { - -bool is_registered_tidy_check(llvm::StringRef check); -std::optional is_fast_tidy_check(llvm::StringRef check); - -struct TidyParams {}; - -class ClangTidyChecker; - -/// Configure to run clang-tidy on the given file. -std::unique_ptr configure(clang::CompilerInstance& instance, - const TidyParams& params); - -} // namespace clice::tidy diff --git a/include/Feature/Diagnostic.h b/include/Feature/Diagnostic.h index 1589aae4..e1c278c8 100644 --- a/include/Feature/Diagnostic.h +++ b/include/Feature/Diagnostic.h @@ -6,7 +6,7 @@ namespace clice { -struct CompilationUnit; +class CompilationUnitRef; } @@ -14,6 +14,6 @@ namespace clice::feature { /// FIXME: This is not correct way, we don't want to couple /// `Feature with Protocol`? Return an array of LSP diagnostic. -json::Value diagnostics(PositionEncodingKind kind, PathMapping mapping, CompilationUnit& unit); +json::Value diagnostics(PositionEncodingKind kind, PathMapping mapping, CompilationUnitRef unit); } // namespace clice::feature diff --git a/include/Feature/DocumentLink.h b/include/Feature/DocumentLink.h index 7ae200ab..f0901e8b 100644 --- a/include/Feature/DocumentLink.h +++ b/include/Feature/DocumentLink.h @@ -18,9 +18,9 @@ struct DocumentLink { using DocumentLinks = std::vector; /// Generate document link for main file. -DocumentLinks document_links(CompilationUnit& unit); +DocumentLinks document_links(CompilationUnitRef unit); /// Generate document link for all source file. -index::Shared index_document_link(CompilationUnit& unit); +index::Shared index_document_link(CompilationUnitRef unit); } // namespace clice::feature diff --git a/include/Feature/DocumentSymbol.h b/include/Feature/DocumentSymbol.h index 724666a4..f91f043c 100644 --- a/include/Feature/DocumentSymbol.h +++ b/include/Feature/DocumentSymbol.h @@ -29,9 +29,9 @@ struct DocumentSymbol { using DocumentSymbols = std::vector; /// Generate document symbols for only interested file. -DocumentSymbols document_symbols(CompilationUnit& unit); +DocumentSymbols document_symbols(CompilationUnitRef unit); /// Generate document symbols for all file in unit. -index::Shared index_document_symbol(CompilationUnit& unit); +index::Shared index_document_symbol(CompilationUnitRef unit); } // namespace clice::feature diff --git a/include/Feature/FoldingRange.h b/include/Feature/FoldingRange.h index 4ab46b18..8986a48b 100644 --- a/include/Feature/FoldingRange.h +++ b/include/Feature/FoldingRange.h @@ -47,9 +47,9 @@ struct FoldingRange { using FoldingRanges = std::vector; /// Generate folding range for interested file only. -FoldingRanges folding_ranges(CompilationUnit& unit); +FoldingRanges folding_ranges(CompilationUnitRef unit); /// Generate folding range for all files. -index::Shared index_folding_range(CompilationUnit& unit); +index::Shared index_folding_range(CompilationUnitRef unit); } // namespace clice::feature diff --git a/include/Feature/Hover.h b/include/Feature/Hover.h index 78e3569c..d7670964 100644 --- a/include/Feature/Hover.h +++ b/include/Feature/Hover.h @@ -66,9 +66,9 @@ struct Hover { }; /// Generate the hover information for the given declaration(for test). -Hover hover(CompilationUnit& unit, const clang::NamedDecl* decl); +Hover hover(CompilationUnitRef unit, const clang::NamedDecl* decl); /// Generate the hover information for the symbol at the given offset. -Hover hover(CompilationUnit& unit, std::uint32_t offset); +Hover hover(CompilationUnitRef unit, std::uint32_t offset); } // namespace clice::feature diff --git a/include/Feature/InlayHint.h b/include/Feature/InlayHint.h index eb007c55..a6b2013e 100644 --- a/include/Feature/InlayHint.h +++ b/include/Feature/InlayHint.h @@ -50,7 +50,7 @@ struct InlayHint { std::vector parts; }; -auto inlay_hints(CompilationUnit& unit, +auto inlay_hints(CompilationUnitRef unit, LocalSourceRange target, const config::InlayHintsOptions& options) -> std::vector; diff --git a/include/Feature/SemanticToken.h b/include/Feature/SemanticToken.h index 737322b2..5e2ecb23 100644 --- a/include/Feature/SemanticToken.h +++ b/include/Feature/SemanticToken.h @@ -21,9 +21,9 @@ struct SemanticToken { using SemanticTokens = std::vector; /// Generate semantic tokens for the interested file only. -SemanticTokens semantic_tokens(CompilationUnit& unit); +SemanticTokens semantic_tokens(CompilationUnitRef unit); /// Generate semantic tokens for all files. -index::Shared index_semantic_token(CompilationUnit& unit); +index::Shared index_semantic_token(CompilationUnitRef unit); } // namespace clice::feature diff --git a/include/Index/IncludeGraph.h b/include/Index/IncludeGraph.h index 9f191d25..2cfbaf2a 100644 --- a/include/Index/IncludeGraph.h +++ b/include/Index/IncludeGraph.h @@ -8,7 +8,7 @@ namespace clice { -class CompilationUnit; +class CompilationUnitRef; } @@ -41,7 +41,7 @@ struct IncludeGraph { /// context. A map between FileID and its include location. llvm::DenseMap file_table; - static IncludeGraph from(CompilationUnit& unit); + static IncludeGraph from(CompilationUnitRef unit); llvm::StringRef path(std::uint32_t path_ref) const { assert(path_ref < paths.size()); diff --git a/include/Index/Shared.h b/include/Index/Shared.h index 5c949854..a943671b 100644 --- a/include/Index/Shared.h +++ b/include/Index/Shared.h @@ -5,7 +5,7 @@ namespace clice { -class CompilationUnit; +class CompilationUnitRef; } diff --git a/include/Index/TUIndex.h b/include/Index/TUIndex.h index cd93ba4e..4a0a4b6f 100644 --- a/include/Index/TUIndex.h +++ b/include/Index/TUIndex.h @@ -75,7 +75,7 @@ struct TUIndex { FileIndex main_file_index; - static TUIndex build(CompilationUnit& unit); + static TUIndex build(CompilationUnitRef unit); }; } // namespace clice::index diff --git a/include/Server/Server.h b/include/Server/Server.h index 7910a93f..9a2794ff 100644 --- a/include/Server/Server.h +++ b/include/Server/Server.h @@ -30,10 +30,6 @@ struct OpenFile { async::Task<> ast_build_task; async::Lock ast_built_lock; - /// Collect all diagnostics in the compilation. - std::shared_ptr> diagnostics = - std::make_unique>(); - /// For header with context, it may have multiple ASTs, use /// an chain to store them. std::unique_ptr next; diff --git a/pixi.lock b/pixi.lock index a502a9c4..bdbbd336 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1,153 +1,6 @@ version: 6 environments: default: - channels: - - url: https://conda.anaconda.org/conda-forge/ - options: - pypi-prerelease-mode: if-necessary-or-explicit - packages: - linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45-default_hfdba357_104.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-20-20.1.8-default_h99862b1_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-20.1.8-default_h36abe19_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/clangxx-20.1.8-default_h363a0c9_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-4.2.1-hc85cc9f_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-20.1.8-hb700be7_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-20.1.8-hffcefe0_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.2.0-h96c4ede_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.2.0-hdb7739f_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.2.0-h96c4ede_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.2.0-h2ead766_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-he073ed8_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp20.1-20.1.8-default_h99862b1_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.17.0-h4e3cde8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-14.2.0-h9c4974d_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm20-20.1.8-hf7376ad_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.2.0-hed042b8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-14.2.0-h9c4974d_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-hf2a90c1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.1-h031cc0b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/lld-20.1.8-hef48ded_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-tools-20-20.1.8-h3b15d91_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-tools-20.1.8-hb700be7_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.2-h32b2ec7_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h0157908_18.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-20-20.1.8-default_h73dfc95_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-20.1.8-default_hf9bcbb7_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-20.1.8-default_h36137df_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.2.1-h54ad630_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-20.1.8-h855ad52_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-20.1.8-he32a8d3_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp20.1-20.1.8-default_h73dfc95_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.17.0-hdece5d2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.7-hf598326_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-20.1.8-h6dc3340_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-20.1.8-h707e725_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm20-20.1.8-h8e0c9ce_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.1-h8eac4d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.1-hba2cd1d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lld-20.1.8-ha4b1419_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-20-20.1.8-h91fd4e7_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-20.1.8-h855ad52_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.13.2-h49c215f_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.2-h40d2674_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h5505292_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - win-64: - - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-h4c7d964_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/clang-20-20.1.8-default_hac490eb_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/clang-20.1.8-default_hac490eb_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/clangxx-20.1.8-default_hac490eb_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.2.1-hdcbee5b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/compiler-rt-20.1.8-h49e36cd_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_win-64-20.1.8-h49e36cd_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.17.0-h43ecb02_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libllvm20-20.1.8-h830ff33_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.51.1-hf5d6505_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.51.0-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.1-h692994f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.1-h5d26750_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/lld-20.1.8-hc465015_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-tools-20.1.8-h752b59f_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.0-h725018a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.2-h4b44e0e_100_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h2b53caa_33.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_33.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_33.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - develop: channels: - url: https://conda.anaconda.org/conda-forge/ indexes: @@ -158,7 +11,7 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45-default_hfdba357_104.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45-default_hfdba357_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda @@ -172,10 +25,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.2.0-hdb7739f_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.2.0-h96c4ede_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.2.0-h2ead766_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.1-h33c6efd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-he073ed8_18.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp20.1-20.1.8-default_h99862b1_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.17.0-h4e3cde8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda @@ -192,15 +46,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.2.0-hed042b8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-hf4e2dac_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-14.2.0-h9c4974d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-hf2a90c1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.1-h031cc0b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lld-20.1.8-hef48ded_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-tools-20-20.1.8-h3b15d91_1.conda @@ -214,7 +68,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h0157908_18.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl @@ -232,10 +86,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-4.2.1-h54ad630_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-20.1.8-h855ad52_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-20.1.8-he32a8d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.1-h38cb7af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp20.1-20.1.8-default_h73dfc95_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.17.0-hdece5d2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.7-hf598326_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-20.1.8-h6dc3340_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-20.1.8-h707e725_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda @@ -247,11 +102,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h1b79a29_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.1-h8eac4d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.1-hba2cd1d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lld-20.1.8-ha4b1419_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-20-20.1.8-h91fd4e7_1.conda @@ -264,7 +119,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.6-h5505292_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl @@ -281,6 +136,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-4.2.1-hdcbee5b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/compiler-rt-20.1.8-h49e36cd_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_win-64-20.1.8-h49e36cd_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.1-h637d24d_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.3-hdf4eb48_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.17.0-h43ecb02_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.3-hac47afa_0.conda @@ -289,11 +145,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libllvm20-20.1.8-h830ff33_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.51.1-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.51.1-hf5d6505_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.51.0-hfd05255_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.1-h692994f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.1-h5d26750_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lld-20.1.8-hc465015_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-tools-20.1.8-h752b59f_1.conda @@ -302,7 +158,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.2-h4b44e0e_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h2b53caa_33.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_33.conda @@ -687,6 +543,17 @@ packages: purls: [] size: 3747046 timestamp: 1764007847963 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45-default_hfdba357_105.conda + sha256: 17fbb32191430310d3eb8309f80a8df54f0d66eda9cf84b2ae5113e6d74e24d8 + md5: e410a8f80e22eb6d840e39ac6a34bd0e + depends: + - ld_impl_linux-64 2.45 default_hbd61a6d_105 + - sysroot_linux-64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + size: 3719982 + timestamp: 1766513109980 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 md5: 51a19bba1b8ebfb60df25cde030b7ebc @@ -1176,6 +1043,17 @@ packages: license_family: MIT size: 12129203 timestamp: 1720853576813 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.1-h33c6efd_0.conda + sha256: 7d6463d0be5092b2ae8f2fad34dc84de83eab8bd44cc0d4be8931881c973c48f + md5: 518e9bbbc3e3486d6a4519192ba690f8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + size: 12722920 + timestamp: 1766299101259 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda sha256: 9ba12c93406f3df5ab0a43db8a4b4ef67a5871dfd401010fbe29b218b2cbe620 md5: 5eb22c1d7b3fc4abb50d92d621583137 @@ -1185,6 +1063,26 @@ packages: license_family: MIT size: 11857802 timestamp: 1720853997952 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.1-h38cb7af_0.conda + sha256: 411177ae27ea780a53f044a349d595638c97b84640a77fab4935db19f76203e2 + md5: 5446161926f45f3a14f7ca9db4d53e3b + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 12372254 + timestamp: 1766299497731 +- conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.1-h637d24d_0.conda + sha256: bee083d5a0f05c380fcec1f30a71ef5518b23563aeb0a21f6b60b792645f9689 + md5: cb8048bed35ef01431184d6a88e46b3e + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + size: 13849749 + timestamp: 1766299627069 - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl name: iniconfig version: 2.3.0 @@ -1274,6 +1172,7 @@ packages: constrains: - binutils_impl_linux-64 2.45 license: GPL-3.0-only + license_family: GPL size: 730831 timestamp: 1766513089214 - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda @@ -1906,6 +1805,17 @@ packages: license: blessing size: 940686 timestamp: 1766319628770 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-hf4e2dac_1.conda + sha256: d614540c55f22ad555633f75e174089018ddfc65c49f447f7bbdbc3c3013bec1 + md5: b1f35e70f047918b49fb4b181e40300e + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.1,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: blessing + size: 943451 + timestamp: 1766319676469 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h1b79a29_1.conda sha256: f2c3cbf2ca7d697098964a748fbf19d6e4adcefa23844ec49f0166f1d36af83c md5: 8c3951797658e10b610929c3e57e9ad9 @@ -2035,6 +1945,7 @@ packages: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: BSD-3-Clause + license_family: BSD size: 40311 timestamp: 1766271528534 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda @@ -2102,6 +2013,35 @@ packages: license_family: MIT size: 45283 timestamp: 1761015644057 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.1-he237659_1.conda + sha256: 047be059033c394bd32ae5de66ce389824352120b3a7c0eff980195f7ed80357 + md5: 417955234eccd8f252b86a265ccdab7f + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.1,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libxml2-16 2.15.1 hca6bf5a_1 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 45402 + timestamp: 1766327161688 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.1-h8d039ee_1.conda + sha256: 59f96fa27cce6a9a27414c5bb301eedda1a1b85cd0d8f5d68f77e46b86e7c95f + md5: fd804ee851e20faca4fecc7df0901d07 + depends: + - __osx >=11.0 + - icu >=78.1,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libxml2-16 2.15.1 h5ef1a60_1 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 40607 + timestamp: 1766327501392 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.1-h9329255_0.conda sha256: c409e384ddf5976a42959265100d6b2c652017d250171eb10bae47ef8166193f md5: fb5ce61da27ee937751162f86beba6d1 @@ -2150,6 +2090,22 @@ packages: purls: [] size: 43209 timestamp: 1761016354235 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.1-h779ef1b_1.conda + sha256: 8b47d5fb00a6ccc0f495d16787ab5f37a434d51965584d6000966252efecf56d + md5: 68dc154b8d415176c07b6995bd3a65d9 + depends: + - icu >=78.1,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libxml2-16 2.15.1 h3cfd58e_1 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + size: 43387 + timestamp: 1766327259710 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-ha9997c6_0.conda sha256: 71436e72a286ef8b57d6f4287626ff91991eb03c7bdbe835280521791efd1434 md5: e7733bc6785ec009e47a224a71917e84 @@ -2166,6 +2122,22 @@ packages: license_family: MIT size: 556302 timestamp: 1761015637262 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-hca6bf5a_1.conda + sha256: 8331284bf9ae641b70cdc0e5866502dd80055fc3b9350979c74bb1d192e8e09e + md5: 3fdd8d99683da9fe279c2f4cecd1e048 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.1,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.1 + license: MIT + license_family: MIT + size: 555747 + timestamp: 1766327145986 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-hf2a90c1_0.conda sha256: f5220ff49efc31431279859049199b9250e79f98c1dee1da12feb74bda2d9cf1 md5: 23720d17346b21efb08d68c2255c8431 @@ -2198,6 +2170,21 @@ packages: license_family: MIT size: 464952 timestamp: 1761016087733 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.1-h5ef1a60_1.conda + sha256: 2d5ab15113b0ba21f4656d387d26ab59e4fbaf3027f5e58a2a4fe370821eb106 + md5: 7eed1026708e26ee512f43a04d9d0027 + depends: + - __osx >=11.0 + - icu >=78.1,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.1 + license: MIT + license_family: MIT + size: 464886 + timestamp: 1766327479416 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.1-h8eac4d7_0.conda sha256: 3f3f9ba64a3fca15802d4eaf2a97696e6dcd916effa6a683756fd9f11245df5a md5: cf7291a970b93fe3bb726879f2037af8 @@ -2214,6 +2201,23 @@ packages: purls: [] size: 464186 timestamp: 1761016258891 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.1-h3cfd58e_1.conda + sha256: a857e941156b7f462063e34e086d212c6ccbc1521ebdf75b9ed66bd90add57dc + md5: 07d73826fde28e7dbaec52a3297d7d26 + depends: + - icu >=78.1,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.1,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libxml2 2.15.1 + license: MIT + license_family: MIT + size: 518964 + timestamp: 1766327232819 - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.1-h692994f_0.conda sha256: 04129dc2df47a01c55e5ccf8a18caefab94caddec41b3b10fbc409e980239eb9 md5: 70ca4626111579c3cd63a7108fe737f9 @@ -2809,6 +2813,7 @@ packages: - libgcc >=14 - ncurses >=6.5,<7.0a0 license: GPL-3.0-only + license_family: GPL purls: [] size: 345073 timestamp: 1765813471974 @@ -2819,6 +2824,7 @@ packages: - __osx >=11.0 - ncurses >=6.5,<7.0a0 license: GPL-3.0-only + license_family: GPL purls: [] size: 313930 timestamp: 1765813902568 @@ -2993,13 +2999,6 @@ packages: license: MIT size: 6535168 timestamp: 1766863032287 -- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - sha256: 5aaa366385d716557e365f0a4e9c3fca43ba196872abbbe3d56bb610d131e192 - md5: 4222072737ccff51314b5ece9c7d6f5a - license: LicenseRef-Public-Domain - purls: [] - size: 122968 - timestamp: 1742727099393 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h8577fbf_1.conda sha256: 865716d3e2ccaca1218462645830d2370ab075a9a118c238728e1231a234bc6c md5: e4e8496b68cf5f25e76fbe67f3856550 @@ -3014,6 +3013,12 @@ packages: purls: [] size: 119204 timestamp: 1765745742795 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + size: 119135 + timestamp: 1767016325805 - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 md5: 71b24316859acd00bdb8b38f5e2ce328 diff --git a/pixi.toml b/pixi.toml index 2fb88e04..c7c2ef4b 100644 --- a/pixi.toml +++ b/pixi.toml @@ -1,3 +1,5 @@ +# tombi: format.rules.table-keys-order.disabled = true + [workspace] name = "clice" version = "0.1.0" @@ -15,30 +17,13 @@ channels = ["conda-forge"] platforms = ["win-64", "linux-64", "osx-arm64"] [environments] -default = ["build"] -develop = ["build", "test"] +default = ["build", "test"] package = ["build", "test", "package"] -format = ["format"] node = ["node"] - -[tasks.build-llvm] -cmd = ["python3", "scripts/build-llvm.py"] - -[tasks.upload-llvm] -args = ["workflow_id", "llvm_version", { "arg" = "branch", default = "main" }] -cmd = """ -gh workflow run upload-llvm.yml \ - --ref {{ branch }} \ - --field workflow_id={{workflow_id}} \ - --field version={{llvm_version}} -""" - -[tasks.delete-artifacts] -args = ["file_name"] -cmd = ["scripts/delete-artifacts.bash", "{{ file_name }}"] +format = ["format"] # ============================================================================== # -# BUILD ENVIRONMENT # +# DEPENDENCIES # # ============================================================================== # [feature.build.dependencies] python = ">=3.13" @@ -61,6 +46,13 @@ scripts = ["scripts/activate_linux.sh"] [feature.build.target.win-64.activation] scripts = ["scripts/activate_asan.bat"] +[feature.test.pypi-dependencies] +pytest = "*" +pytest-asyncio = ">=1.1.0" + +[feature.package.dependencies] +xz = ">=5.8.1,<6" + # ============================================================================== # # CMAKE # # ============================================================================== # @@ -97,14 +89,14 @@ depends-on = [ args = [{ arg = "type", default = "RelWithDebInfo" }] cmd = './build/{{ type }}/bin/unit_tests --test-dir="./tests/data"' -[feature.build.tasks.integration-test] +[feature.test.tasks.integration-test] args = [{ arg = "type", default = "RelWithDebInfo" }] cmd = """ pytest -s --log-cli-level=INFO tests/integration \ --executable=./build/{{ type }}/bin/clice """ -[feature.build.tasks.test] +[feature.test.tasks.test] args = [{ arg = "type", default = "RelWithDebInfo" }] depends-on = [ { task = "unit-test", args = ["{{ type }}"] }, @@ -134,16 +126,9 @@ depends-on = [ { task = "xmake-build" }, ] -[feature.build.tasks.xmake-test] +[feature.test.tasks.xmake-test] cmd = "xmake test --verbose" -[feature.test.pypi-dependencies] -pytest = "*" -pytest-asyncio = ">=1.1.0" - -[feature.package.dependencies] -xz = ">=5.8.1,<6" - [feature.package.tasks.package] cmd = """ xmake config --yes --toolchain=clang --mode=releasedbg \ @@ -151,6 +136,25 @@ xmake config --yes --toolchain=clang --mode=releasedbg \ xmake pack --verbose """ +# ============================================================================== # +# HELPER TASKS # +# ============================================================================== # +[tasks.build-llvm] +cmd = ["python3", "scripts/build-llvm.py"] + +[tasks.upload-llvm] +args = ["workflow_id", "llvm_version", { "arg" = "branch", default = "main" }] +cmd = """ +gh workflow run upload-llvm.yml \ + --ref {{ branch }} \ + --field workflow_id={{workflow_id}} \ + --field version={{llvm_version}} +""" + +[tasks.delete-artifacts] +args = ["file_name"] +cmd = ["scripts/delete-artifacts.bash", "{{ file_name }}"] + # ============================================================================== # # DOCS & VSCODE EXTENSION # # ============================================================================== # diff --git a/src/AST/Selection.cpp b/src/AST/Selection.cpp index 3a1ea0f6..e85e1759 100644 --- a/src/AST/Selection.cpp +++ b/src/AST/Selection.cpp @@ -286,7 +286,7 @@ bool is_first_expansion(clang::FileID target, class SelectionTester { public: // The selection is offsets [SelBegin, SelEnd) in SelFile. - SelectionTester(CompilationUnit& unit, + SelectionTester(CompilationUnitRef unit, clang::FileID selected_file_id, LocalSourceRange selected_range, const clang::SourceManager& source_manager) : @@ -712,7 +712,7 @@ class SelectionVisitor : public clang::RecursiveASTVisitor { public: // Runs the visitor to gather selected nodes and their ancestors. // If there is any selection, the root (TUDecl) is the first node. - static std::deque collect(CompilationUnit& unit, + static std::deque collect(CompilationUnitRef unit, const clang::PrintingPolicy& printing_policy, LocalSourceRange range, clang::FileID fid) { @@ -871,7 +871,7 @@ public: private: using Base = RecursiveASTVisitor; - SelectionVisitor(CompilationUnit& unit, + SelectionVisitor(CompilationUnitRef unit, const clang::PrintingPolicy& printing_policy, LocalSourceRange range, clang::FileID selected_file) : @@ -1135,7 +1135,7 @@ private: clang::SourceManager& SM; const clang::LangOptions& lang_opts; const clang::PrintingPolicy& print_policy; - CompilationUnit& unit; + CompilationUnitRef unit; std::stack stack; SelectionTester checker; IntervalSet unclaimed_expanded_tokens; @@ -1186,7 +1186,7 @@ std::string SelectionTree::Node::kind() const { return std::move(OS.str()); } -bool SelectionTree::create_each(CompilationUnit& unit, +bool SelectionTree::create_each(CompilationUnitRef unit, LocalSourceRange range, llvm::function_ref callback) { auto [begin, end] = range; @@ -1227,7 +1227,7 @@ bool SelectionTree::create_each(CompilationUnit& unit, return false; } -SelectionTree SelectionTree::create_right(CompilationUnit& unit, LocalSourceRange range) { +SelectionTree SelectionTree::create_right(CompilationUnitRef unit, LocalSourceRange range) { std::optional result; create_each(unit, range, [&](SelectionTree T) { result = std::move(T); @@ -1236,7 +1236,7 @@ SelectionTree SelectionTree::create_right(CompilationUnit& unit, LocalSourceRang return std::move(*result); } -SelectionTree::SelectionTree(CompilationUnit& unit, LocalSourceRange range) : +SelectionTree::SelectionTree(CompilationUnitRef unit, LocalSourceRange range) : print_policy(unit.context().getLangOpts()) { // No fundamental reason the selection needs to be in the main file, // but that's all clice has needed so far. diff --git a/src/Compiler/Command.cpp b/src/Compiler/Command.cpp index 00880cbf..2cf3b91a 100644 --- a/src/Compiler/Command.cpp +++ b/src/Compiler/Command.cpp @@ -703,7 +703,7 @@ CompilationContext CompilationDatabase::lookup(llvm::StringRef file, append_arg(fs::resource_dir); } - if(options.query_toolchain) { + if(info && options.query_toolchain) { auto callback = [&](const char* s) { return save_string(s).data(); }; diff --git a/src/Compiler/Compilation.cpp b/src/Compiler/Compilation.cpp index 433d46dd..5c28bcf4 100644 --- a/src/Compiler/Compilation.cpp +++ b/src/Compiler/Compilation.cpp @@ -1,13 +1,12 @@ #include "Compiler/Compilation.h" -#include "CompilationUnitImpl.h" -#include "TidyImpl.h" +#include "Implement.h" #include "AST/Utility.h" #include "Compiler/Command.h" #include "Compiler/Diagnostic.h" -#include "Compiler/Tidy.h" #include "Support/Logging.h" +#include "llvm/Support/Error.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/PreprocessorOptions.h" @@ -97,7 +96,8 @@ private: /// create a `clang::CompilerInvocation` for compilation, it set and reset /// all necessary arguments and flags for clice compilation. -auto create_invocation(CompilationParams& params, +auto create_invocation(CompilationUnitRef::Self& self, + CompilationParams& params, llvm::IntrusiveRefCntPtr& diagnostic_engine) -> std::unique_ptr { if(params.arguments.empty()) { @@ -137,12 +137,16 @@ auto create_invocation(CompilationParams& params, } auto& pp_opts = invocation->getPreprocessorOpts(); - assert(!pp_opts.RetainRemappedFileBuffers && "RetainRemappedFileBuffers should be false"); + + // CompilerInstance does not deterministically clear RetainRemappedFileBuffers, + // especially if compilation aborts early, so we keep them alive and clean up + // in CompilationUnit's destructor instead. + pp_opts.RetainRemappedFileBuffers = true; for(auto& [file, buffer]: params.buffers) { - pp_opts.addRemappedFile(file, buffer.release()); + pp_opts.addRemappedFile(file, buffer.get()); } - params.buffers.clear(); + self.remapped_buffers = std::move(params.buffers); auto [pch, bound] = params.pch; pp_opts.ImplicitPCHInclude = std::move(pch); @@ -155,12 +159,23 @@ auto create_invocation(CompilationParams& params, pp_opts.WriteCommentListToPCH = false; auto& header_search_opts = invocation->getHeaderSearchOpts(); + header_search_opts.Verbose = false; for(auto& [name, path]: params.pcms) { header_search_opts.PrebuiltModuleFiles.try_emplace(name.str(), std::move(path)); } auto& front_opts = invocation->getFrontendOpts(); front_opts.DisableFree = false; + front_opts.ShowHelp = false; + front_opts.ShowStats = false; + front_opts.ShowVersion = false; + front_opts.StatsFile = ""; + front_opts.TimeTracePath = ""; + front_opts.TimeTraceVerbose = false; + front_opts.TimeTraceGranularity = false; + front_opts.PrintSupportedCPUs = false; + front_opts.PrintEnabledExtensions = false; + front_opts.PrintSupportedExtensions = false; /// Compiler flags (like gcc/clang's -M, -MD, -MMD, -H, or msvc's /showIncludes) /// can generate dependency files or print included headers to stdout/stderr. @@ -190,188 +205,162 @@ auto create_invocation(CompilationParams& params, return invocation; } -/// Do nothing before or after compile state. -constexpr static auto no_hook = [](auto& /*ignore*/) { -}; - -template -CompilationResult run_clang(CompilationParams& params, - const BeforeExecute& before_execute = no_hook, - const AfterExecute& after_execute = no_hook) { - namespace chrono = std::chrono; - auto build_at = chrono::system_clock::now().time_since_epoch(); - auto build_start = chrono::steady_clock::now().time_since_epoch(); - - auto diagnostics = - params.diagnostics ? params.diagnostics : std::make_shared>(); - auto diagnostic_consumer = Diagnostic::create(diagnostics); +CompilationStatus run_clang(CompilationUnitRef::Self& self, + CompilationParams& params, + std::unique_ptr action, + llvm::function_ref before_execute) { + std::unique_ptr diagnostic_consumer = create_diagnostic(&self); /// Temporary diagnostic engine, only used for command line parsing. /// For compilation, we need to create a new diagnostic engine. See also /// https://github.com/llvm/llvm-project/pull/139584#issuecomment-2920704282. clang::DiagnosticOptions options; - auto diagnostic_engine = clang::CompilerInstance::createDiagnostics(*params.vfs, - options, - diagnostic_consumer.get(), - false); + llvm::IntrusiveRefCntPtr diagnostic_engine = + clang::CompilerInstance::createDiagnostics(*params.vfs, + options, + diagnostic_consumer.get(), + false); + if(!diagnostic_engine) { + return CompilationStatus::SetupFail; + } - auto invocation = create_invocation(params, diagnostic_engine); + std::unique_ptr invocation = create_invocation(self, params, diagnostic_engine); if(!invocation) { - return std::unexpected("Fail to create compilation invocation!"); + return CompilationStatus::SetupFail; } - auto instance = std::make_unique(std::move(invocation)); - instance->createDiagnostics(*params.vfs, diagnostic_consumer.release(), true); + self.instance = std::make_unique(std::move(invocation)); + auto& instance = *self.instance; + instance.createDiagnostics(*params.vfs, diagnostic_consumer.release(), true); - if(auto remapping = clang::createVFSFromCompilerInvocation(instance->getInvocation(), - instance->getDiagnostics(), + if(auto remapping = clang::createVFSFromCompilerInvocation(instance.getInvocation(), + instance.getDiagnostics(), params.vfs)) { - instance->createFileManager(std::move(remapping)); + instance.createFileManager(std::move(remapping)); } - if(!instance->createTarget()) { - return std::unexpected("Fail to create target!"); + if(!instance.createTarget()) { + return CompilationStatus::SetupFail; } - /// Adjust the compiler instance, for example, set preamble or modules. - before_execute(*instance); + if(before_execute) { + before_execute(instance); + } - /// Frontend information ... - std::vector top_level_decls; - llvm::DenseMap directives; - std::optional token_collector; - - auto action = std::make_unique( - std::make_unique(), + self.action = std::make_unique( + std::move(action), /// We only collect top level declarations for parse main file. - (params.clang_tidy || params.kind == CompilationUnit::Content) ? &top_level_decls : nullptr, + (params.clang_tidy || params.kind == CompilationKind::Content) ? &self.top_level_decls + : nullptr, params.stop); - if(!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) { - return std::unexpected("Fail to begin source file"); + if(!self.action->BeginSourceFile(instance, instance.getFrontendOpts().Inputs[0])) { + self.action.reset(); + return CompilationStatus::SetupFail; } - auto& pp = instance->getPreprocessor(); /// FIXME: include-fixer, etc? - /// Setup clang-tidy - std::unique_ptr checker; + /// Add PPCallbacks to collect preprocessing information. + self.collect_directives(); + if(params.clang_tidy) { - tidy::TidyParams tidy_params; - checker = tidy::configure(*instance, tidy_params); - /// TODO: We should make the lifetime of diagnostic consumer more explicit. - static_cast(instance->getDiagnosticClient()).checker = checker.get(); + self.configure_tidy({}); } - /// `BeginSourceFile` may create new preprocessor, so all operations related to preprocessor - /// should be done after `BeginSourceFile`. - Directive::attach(pp, directives); - - /// It is not necessary to collect tokens if we are running code completion. - /// And in fact will cause assertion failure. - if(!instance->hasCodeCompletionConsumer()) { - token_collector.emplace(pp); + std::optional token_collector; + if(!instance.hasCodeCompletionConsumer()) { + /// It is not necessary to collect tokens if we are running code completion. + /// And in fact will cause assertion failure. + token_collector.emplace(instance.getPreprocessor()); } - if(auto error = action->Execute()) { - return std::unexpected(std::format("Failed to execute action, because {} ", error)); + if(auto error = self.action->Execute()) { + // Upstream FrontendAction::Execute() always returns success (errors go through + // diagnostics); log here only as a guard in case a custom action ever returns + // an unexpected llvm::Error. + LOG_ERROR("FrontendAction::Execute failed: {}", error); + return CompilationStatus::FatalError; } /// If the output file is not empty, it represents that we are /// generating a PCH or PCM. If error occurs, the AST must be /// invalid to some extent, serialization of such AST may result /// in crash frequently. So forbidden it here and return as error. - if(!instance->getFrontendOpts().OutputFile.empty() && - instance->getDiagnostics().hasErrorOccurred()) { - action->EndSourceFile(); - return std::unexpected("Fail to build PCH or PCM, error occurs in compilation."); + if(!instance.getFrontendOpts().OutputFile.empty() && + instance.getDiagnostics().hasErrorOccurred()) { + return CompilationStatus::FatalError; } /// Check whether the compilation is canceled, if so we think /// it is an error. if(params.stop && params.stop->load()) { - action->EndSourceFile(); - return std::unexpected("Compilation is canceled."); + self.action->EndSourceFile(); + self.action.reset(); + return CompilationStatus::Cancelled; } - std::optional token_buffer; if(token_collector) { - token_buffer = std::move(*token_collector).consume(); + self.buffer = std::move(*token_collector).consume(); } - // Must be called before EndSourceFile because the ast context can be destroyed later. - if(checker) { - // AST traversals should exclude the preamble, to avoid performance cliffs. - // TODO: is it okay to affect the unit-level traversal scope here? - instance->getASTContext().setTraversalScope(top_level_decls); - checker->finder.matchAST(instance->getASTContext()); + self.run_tidy(); + + if(instance.hasSema()) { + self.resolver.emplace(instance.getSema()); } - /// XXX: This is messy: clang-tidy checks flush some diagnostics at EOF. - /// However Action->EndSourceFile() would destroy the ASTContext! - /// So just inform the preprocessor of EOF, while keeping everything alive. - pp.EndSourceFile(); + return CompilationStatus::Completed; +} - /// FIXME: getDependencies currently return ArrayRef, which actually results in - /// extra copy. It would be great to avoid this copy. +CompilationUnit run_clang(CompilationParams& params, + std::unique_ptr action, + llvm::function_ref before_execute = {}, + llvm::function_ref after_execute = {}) { + auto self = new CompilationUnitRef::Self(); + self->kind = params.kind; - std::optional resolver; - if(instance->hasSema()) { - resolver.emplace(instance->getSema()); + using namespace std::chrono; + self->build_at = duration_cast(system_clock::now().time_since_epoch()); + auto build_start = steady_clock::now().time_since_epoch(); + + self->status = run_clang(*self, params, std::move(action), before_execute); + + auto build_end = steady_clock::now().time_since_epoch(); + self->build_duration = duration_cast(build_end - build_start); + + if(self->status == CompilationStatus::Completed && after_execute) { + after_execute(self); } - if(checker) { - /// Avoid dangling pointer. - static_cast(instance->getDiagnosticClient()).checker = nullptr; - } - - auto build_end = chrono::steady_clock::now().time_since_epoch(); - - auto impl = new CompilationUnit::Impl{ - .interested = instance->getSourceManager().getMainFileID(), - .src_mgr = instance->getSourceManager(), - .action = std::move(action), - .instance = std::move(instance), - .resolver = std::move(resolver), - .buffer = std::move(token_buffer), - .directives = std::move(directives), - .path_cache = llvm::DenseMap(), - .symbol_hash_cache = llvm::DenseMap(), - .diagnostics = std::move(diagnostics), - .top_level_decls = std::move(top_level_decls), - .build_at = chrono::duration_cast(build_at), - .build_duration = chrono::duration_cast(build_end - build_start), - }; - - CompilationUnit unit(params.kind, impl); - after_execute(unit); - return unit; + return CompilationUnit(self); } } // namespace -CompilationResult preprocess(CompilationParams& params) { - return run_clang(params); +CompilationUnit preprocess(CompilationParams& params) { + return run_clang(params, std::make_unique()); } -CompilationResult compile(CompilationParams& params) { - return run_clang(params, [](clang::CompilerInstance& instance) { - /// Make sure the output file is empty. - instance.getFrontendOpts().OutputFile.clear(); - }); +CompilationUnit compile(CompilationParams& params) { + return run_clang(params, + std::make_unique(), + [](clang::CompilerInstance& instance) { + /// Make sure the output file is empty. + instance.getFrontendOpts().OutputFile.clear(); + }); } -CompilationResult compile(CompilationParams& params, PCHInfo& out) { +CompilationUnit compile(CompilationParams& params, PCHInfo& out) { assert(!params.output_file.empty() && "PCH file path cannot be empty"); /// Record the begin time of PCH building. auto now = std::chrono::system_clock::now().time_since_epoch(); out.mtime = std::chrono::duration_cast(now).count(); - return run_clang( + return run_clang( params, + std::make_unique(), [&](clang::CompilerInstance& instance) { /// Set options to generate PCH. instance.getFrontendOpts().OutputFile = params.output_file.str(); @@ -384,7 +373,7 @@ CompilationResult compile(CompilationParams& params, PCHInfo& out) { instance.getLangOpts().CompilingPCH = true; }, - [&](CompilationUnit& unit) { + [&](CompilationUnitRef unit) { out.path = params.output_file.str(); out.preamble = unit.interested_content(); out.deps = unit.deps(); @@ -392,11 +381,12 @@ CompilationResult compile(CompilationParams& params, PCHInfo& out) { }); } -CompilationResult compile(CompilationParams& params, PCMInfo& out) { +CompilationUnit compile(CompilationParams& params, PCMInfo& out) { assert(!params.output_file.empty() && "PCM file path cannot be empty"); - return run_clang( + return run_clang( params, + std::make_unique(), [&](clang::CompilerInstance& instance) { /// Set options to generate PCH. instance.getFrontendOpts().OutputFile = params.output_file.str(); @@ -405,7 +395,7 @@ CompilationResult compile(CompilationParams& params, PCMInfo& out) { out.srcPath = instance.getFrontendOpts().Inputs[0].getFile(); }, - [&](CompilationUnit& unit) { + [&](CompilationUnitRef unit) { out.path = params.output_file.str(); for(auto& [name, path]: params.pcms) { @@ -414,7 +404,7 @@ CompilationResult compile(CompilationParams& params, PCMInfo& out) { }); } -CompilationResult complete(CompilationParams& params, clang::CodeCompleteConsumer* consumer) { +CompilationUnit complete(CompilationParams& params, clang::CodeCompleteConsumer* consumer) { auto& [file, offset] = params.completion; /// The location of clang is 1-1 based. @@ -434,13 +424,15 @@ CompilationResult complete(CompilationParams& params, clang::CodeCompleteConsume column += 1; } - return run_clang(params, [&](clang::CompilerInstance& instance) { - /// Set options to run code completion. - instance.getFrontendOpts().CodeCompletionAt.FileName = std::move(file); - instance.getFrontendOpts().CodeCompletionAt.Line = line; - instance.getFrontendOpts().CodeCompletionAt.Column = column; - instance.setCodeCompletionConsumer(consumer); - }); + return run_clang(params, + std::make_unique(), + [&](clang::CompilerInstance& instance) { + /// Set options to run code completion. + instance.getFrontendOpts().CodeCompletionAt.FileName = std::move(file); + instance.getFrontendOpts().CodeCompletionAt.Line = line; + instance.getFrontendOpts().CodeCompletionAt.Column = column; + instance.setCodeCompletionConsumer(consumer); + }); } } // namespace clice diff --git a/src/Compiler/CompilationUnit.cpp b/src/Compiler/CompilationUnit.cpp index 54acfd17..ff95d57c 100644 --- a/src/Compiler/CompilationUnit.cpp +++ b/src/Compiler/CompilationUnit.cpp @@ -1,38 +1,33 @@ -#include "CompilationUnitImpl.h" +#include "Implement.h" #include "AST/Utility.h" #include "Index/USR.h" namespace clice { -CompilationUnit::~CompilationUnit() { - if(impl && impl->action) { - auto instance = impl->instance.get(); - // We already notified the pp of end-of-file earlier, so detach it first. - // We must keep it alive until after EndSourceFile(), Sema relies on this. - std::shared_ptr pp = instance->getPreprocessorPtr(); - instance->setPreprocessor(nullptr); // Detach so we don't send EOF again - impl->action->EndSourceFile(); - } - - delete impl; +CompilationKind CompilationUnitRef::kind() { + return self->kind; } -auto CompilationUnit::file_id(llvm::StringRef file) -> clang::FileID { - auto entry = impl->src_mgr.getFileManager().getFileRef(file); +CompilationStatus CompilationUnitRef::status() { + return self->status; +} + +auto CompilationUnitRef::file_id(llvm::StringRef file) -> clang::FileID { + auto entry = self->SM().getFileManager().getFileRef(file); if(entry) { - return impl->src_mgr.translateFile(*entry); + return self->SM().translateFile(*entry); } return clang::FileID(); } -auto CompilationUnit::decompose_location(clang::SourceLocation location) +auto CompilationUnitRef::decompose_location(clang::SourceLocation location) -> std::pair { assert(location.isFileID() && "Decompose macro location is meaningless!"); - return impl->src_mgr.getDecomposedLoc(location); + return self->SM().getDecomposedLoc(location); } -auto CompilationUnit::decompose_range(clang::SourceRange range) +auto CompilationUnitRef::decompose_range(clang::SourceRange range) -> std::pair { auto [begin, end] = range; assert(begin.isValid() && end.isValid() && "Invalid source range"); @@ -62,7 +57,7 @@ auto CompilationUnit::decompose_range(clang::SourceRange range) } } -auto CompilationUnit::decompose_expansion_range(clang::SourceRange range) +auto CompilationUnitRef::decompose_expansion_range(clang::SourceRange range) -> std::pair { auto [begin, end] = range; if(begin == end) { @@ -73,21 +68,21 @@ auto CompilationUnit::decompose_expansion_range(clang::SourceRange range) } } -auto CompilationUnit::file_id(clang::SourceLocation location) -> clang::FileID { - return impl->src_mgr.getFileID(location); +auto CompilationUnitRef::file_id(clang::SourceLocation location) -> clang::FileID { + return self->SM().getFileID(location); } -auto CompilationUnit::file_offset(clang::SourceLocation location) -> std::uint32_t { - return impl->src_mgr.getFileOffset(location); +auto CompilationUnitRef::file_offset(clang::SourceLocation location) -> std::uint32_t { + return self->SM().getFileOffset(location); } -auto CompilationUnit::file_path(clang::FileID fid) -> llvm::StringRef { +auto CompilationUnitRef::file_path(clang::FileID fid) -> llvm::StringRef { assert(fid.isValid() && "Invalid fid"); - if(auto it = impl->path_cache.find(fid); it != impl->path_cache.end()) { + if(auto it = self->path_cache.find(fid); it != self->path_cache.end()) { return it->second; } - auto entry = impl->src_mgr.getFileEntryRefForID(fid); + auto entry = self->SM().getFileEntryRefForID(fid); assert(entry && "Invalid file entry"); llvm::SmallString<128> path; @@ -102,31 +97,31 @@ auto CompilationUnit::file_path(clang::FileID fid) -> llvm::StringRef { /// Allocate the path in the storage. auto size = path.size(); - auto data = impl->path_storage.Allocate(size + 1); + auto data = self->path_storage.Allocate(size + 1); memcpy(data, path.data(), size); data[size] = '\0'; - auto [it, inserted] = impl->path_cache.try_emplace(fid, llvm::StringRef(data, size)); + auto [it, inserted] = self->path_cache.try_emplace(fid, llvm::StringRef(data, size)); assert(inserted && "File path already exists"); return it->second; } -auto CompilationUnit::file_content(clang::FileID fid) -> llvm::StringRef { - return impl->src_mgr.getBufferData(fid); +auto CompilationUnitRef::file_content(clang::FileID fid) -> llvm::StringRef { + return self->SM().getBufferData(fid); } -auto CompilationUnit::interested_file() -> clang::FileID { - return impl->interested; +auto CompilationUnitRef::interested_file() -> clang::FileID { + return self->SM().getMainFileID(); } -auto CompilationUnit::interested_content() -> llvm::StringRef { - return file_content(impl->interested); +auto CompilationUnitRef::interested_content() -> llvm::StringRef { + return file_content(interested_file()); } -bool CompilationUnit::is_builtin_file(clang::FileID fid) { +bool CompilationUnitRef::is_builtin_file(clang::FileID fid) { // No FileEntryRef => built-in/command line/scratch. - if(!impl->src_mgr.getFileEntryRefForID(fid)) { - if(auto buffer = impl->src_mgr.getBufferOrNone(fid)) { + if(!self->SM().getFileEntryRefForID(fid)) { + if(auto buffer = self->SM().getBufferOrNone(fid)) { auto name = buffer->getBufferIdentifier(); return name == "" || name == "" || name == ""; } @@ -135,45 +130,46 @@ bool CompilationUnit::is_builtin_file(clang::FileID fid) { return false; } -auto CompilationUnit::start_location(clang::FileID fid) -> clang::SourceLocation { - return impl->src_mgr.getLocForStartOfFile(fid); +auto CompilationUnitRef::start_location(clang::FileID fid) -> clang::SourceLocation { + return self->SM().getLocForStartOfFile(fid); } -auto CompilationUnit::end_location(clang::FileID fid) -> clang::SourceLocation { - return impl->src_mgr.getLocForEndOfFile(fid); +auto CompilationUnitRef::end_location(clang::FileID fid) -> clang::SourceLocation { + return self->SM().getLocForEndOfFile(fid); } -auto CompilationUnit::spelling_location(clang::SourceLocation loc) -> clang::SourceLocation { - return impl->src_mgr.getSpellingLoc(loc); +auto CompilationUnitRef::spelling_location(clang::SourceLocation loc) -> clang::SourceLocation { + return self->SM().getSpellingLoc(loc); } -auto CompilationUnit::expansion_location(clang::SourceLocation location) -> clang::SourceLocation { - return impl->src_mgr.getExpansionLoc(location); -} - -auto CompilationUnit::file_location(clang::SourceLocation location) -> clang::SourceLocation { - return impl->src_mgr.getFileLoc(location); -} - -auto CompilationUnit::include_location(clang::FileID fid) -> clang::SourceLocation { - return impl->src_mgr.getIncludeLoc(fid); -} - -auto CompilationUnit::presumed_location(clang::SourceLocation location) -> clang::PresumedLoc { - return impl->src_mgr.getPresumedLoc(location, false); -} - -auto CompilationUnit::create_location(clang::FileID fid, std::uint32_t offset) +auto CompilationUnitRef::expansion_location(clang::SourceLocation location) -> clang::SourceLocation { - return impl->src_mgr.getComposedLoc(fid, offset); + return self->SM().getExpansionLoc(location); } -auto CompilationUnit::spelled_tokens(clang::FileID fid) -> TokenRange { - return impl->buffer->spelledTokens(fid); +auto CompilationUnitRef::file_location(clang::SourceLocation location) -> clang::SourceLocation { + return self->SM().getFileLoc(location); } -auto CompilationUnit::spelled_tokens(clang::SourceRange range) -> TokenRange { - auto tokens = impl->buffer->spelledForExpanded(impl->buffer->expandedTokens(range)); +auto CompilationUnitRef::include_location(clang::FileID fid) -> clang::SourceLocation { + return self->SM().getIncludeLoc(fid); +} + +auto CompilationUnitRef::presumed_location(clang::SourceLocation location) -> clang::PresumedLoc { + return self->SM().getPresumedLoc(location, false); +} + +auto CompilationUnitRef::create_location(clang::FileID fid, std::uint32_t offset) + -> clang::SourceLocation { + return self->SM().getComposedLoc(fid, offset); +} + +auto CompilationUnitRef::spelled_tokens(clang::FileID fid) -> TokenRange { + return self->buffer->spelledTokens(fid); +} + +auto CompilationUnitRef::spelled_tokens(clang::SourceRange range) -> TokenRange { + auto tokens = self->buffer->spelledForExpanded(self->buffer->expandedTokens(range)); if(!tokens) { return {}; } @@ -181,72 +177,72 @@ auto CompilationUnit::spelled_tokens(clang::SourceRange range) -> TokenRange { return *tokens; } -auto CompilationUnit::spelled_tokens_touch(clang::SourceLocation location) -> TokenRange { - return clang::syntax::spelledTokensTouching(location, *impl->buffer); +auto CompilationUnitRef::spelled_tokens_touch(clang::SourceLocation location) -> TokenRange { + return clang::syntax::spelledTokensTouching(location, *self->buffer); } -auto CompilationUnit::expanded_tokens() -> TokenRange { - return impl->buffer->expandedTokens(); +auto CompilationUnitRef::expanded_tokens() -> TokenRange { + return self->buffer->expandedTokens(); } -auto CompilationUnit::expanded_tokens(clang::SourceRange range) -> TokenRange { - return impl->buffer->expandedTokens(range); +auto CompilationUnitRef::expanded_tokens(clang::SourceRange range) -> TokenRange { + return self->buffer->expandedTokens(range); } -auto CompilationUnit::expansions_overlapping(TokenRange spelled_tokens) +auto CompilationUnitRef::expansions_overlapping(TokenRange spelled_tokens) -> std::vector { - return impl->buffer->expansionsOverlapping(spelled_tokens); + return self->buffer->expansionsOverlapping(spelled_tokens); } -auto CompilationUnit::token_length(clang::SourceLocation location) -> std::uint32_t { - return clang::Lexer::MeasureTokenLength(location, impl->src_mgr, impl->instance->getLangOpts()); +auto CompilationUnitRef::token_length(clang::SourceLocation location) -> std::uint32_t { + return clang::Lexer::MeasureTokenLength(location, self->SM(), self->instance->getLangOpts()); } -auto CompilationUnit::token_spelling(clang::SourceLocation location) -> llvm::StringRef { - return llvm::StringRef(impl->src_mgr.getCharacterData(location), token_length(location)); +auto CompilationUnitRef::token_spelling(clang::SourceLocation location) -> llvm::StringRef { + return llvm::StringRef(self->SM().getCharacterData(location), token_length(location)); } -auto CompilationUnit::module_name() -> llvm::StringRef { - return impl->instance->getPreprocessor().getNamedModuleName(); +auto CompilationUnitRef::module_name() -> llvm::StringRef { + return self->instance->getPreprocessor().getNamedModuleName(); } -bool CompilationUnit::is_module_interface_unit() { - return impl->instance->getPreprocessor().isInNamedInterfaceUnit(); +bool CompilationUnitRef::is_module_interface_unit() { + return self->instance->getPreprocessor().isInNamedInterfaceUnit(); } -auto CompilationUnit::diagnostics() -> llvm::ArrayRef { - return *impl->diagnostics; +auto CompilationUnitRef::diagnostics() -> std::vector& { + return self->diagnostics; } -auto CompilationUnit::top_level_decls() -> llvm::ArrayRef { - return impl->top_level_decls; +auto CompilationUnitRef::top_level_decls() -> llvm::ArrayRef { + return self->top_level_decls; } -std::chrono::milliseconds CompilationUnit::build_at() { - return impl->build_at; +std::chrono::milliseconds CompilationUnitRef::build_at() { + return self->build_at; } -std::chrono::milliseconds CompilationUnit::build_duration() { - return impl->build_duration; +std::chrono::milliseconds CompilationUnitRef::build_duration() { + return self->build_duration; } -clang::LangOptions& CompilationUnit::lang_options() { - return impl->instance->getLangOpts(); +clang::LangOptions& CompilationUnitRef::lang_options() { + return self->instance->getLangOpts(); } -std::vector CompilationUnit::deps() { +std::vector CompilationUnitRef::deps() { llvm::StringSet<> deps; /// FIXME: consider `#embed` and `__has_embed`. - for(auto& [fid, diretive]: directives()) { - for(auto& include: diretive.includes) { + for(auto& [fid, directive]: directives()) { + for(auto& include: directive.includes) { if(!include.skipped) { deps.try_emplace(file_path(include.fid)); } } - for(auto& has_include: diretive.has_includes) { + for(auto& has_include: directive.has_includes) { if(has_include.fid.isValid()) { deps.try_emplace(file_path(has_include.fid)); } @@ -262,69 +258,73 @@ std::vector CompilationUnit::deps() { return result; } -index::SymbolID CompilationUnit::getSymbolID(const clang::NamedDecl* decl) { +index::SymbolID CompilationUnitRef::getSymbolID(const clang::NamedDecl* decl) { uint64_t hash; - auto iter = impl->symbol_hash_cache.find(decl); - if(iter != impl->symbol_hash_cache.end()) { + auto iter = self->symbol_hash_cache.find(decl); + if(iter != self->symbol_hash_cache.end()) { hash = iter->second; } else { llvm::SmallString<128> usr; index::generateUSRForDecl(decl, usr); hash = llvm::xxh3_64bits(usr); - impl->symbol_hash_cache.try_emplace(decl, hash); + self->symbol_hash_cache.try_emplace(decl, hash); } return index::SymbolID{hash, ast::name_of(decl)}; } -index::SymbolID CompilationUnit::getSymbolID(const clang::MacroInfo* macro) { +index::SymbolID CompilationUnitRef::getSymbolID(const clang::MacroInfo* macro) { std::uint64_t hash; auto name = token_spelling(macro->getDefinitionLoc()); - auto iter = impl->symbol_hash_cache.find(macro); - if(iter != impl->symbol_hash_cache.end()) { + auto iter = self->symbol_hash_cache.find(macro); + if(iter != self->symbol_hash_cache.end()) { hash = iter->second; } else { llvm::SmallString<128> usr; - index::generateUSRForMacro(name, macro->getDefinitionLoc(), impl->src_mgr, usr); + index::generateUSRForMacro(name, macro->getDefinitionLoc(), self->SM(), usr); hash = llvm::xxh3_64bits(usr); - impl->symbol_hash_cache.try_emplace(macro, hash); + self->symbol_hash_cache.try_emplace(macro, hash); } return index::SymbolID{hash, name.str()}; } -const llvm::DenseSet& CompilationUnit::files() { - if(impl->all_files.empty()) { +const llvm::DenseSet& CompilationUnitRef::files() { + if(self->all_files.empty()) { /// FIXME: handle preamble and embed file id. - for(auto& [fid, diretive]: directives()) { - for(auto& include: diretive.includes) { - if(!include.skipped) { - impl->all_files.insert(include.fid); + for(auto& [fid, directive]: directives()) { + for(auto& include: directive.includes) { + if(!include.skipped && include.fid.isValid()) { + self->all_files.insert(include.fid); } } } - impl->all_files.insert(impl->src_mgr.getMainFileID()); + self->all_files.insert(self->SM().getMainFileID()); } - return impl->all_files; + return self->all_files; } -clang::TranslationUnitDecl* CompilationUnit::tu() { - return impl->instance->getASTContext().getTranslationUnitDecl(); +clang::TranslationUnitDecl* CompilationUnitRef::tu() { + return self->instance->getASTContext().getTranslationUnitDecl(); } -llvm::DenseMap& CompilationUnit::directives() { - return impl->directives; +llvm::DenseMap& CompilationUnitRef::directives() { + return self->directives; } -TemplateResolver& CompilationUnit::resolver() { - assert(impl->resolver && "Template resolver is not available"); - return *impl->resolver; +TemplateResolver& CompilationUnitRef::resolver() { + assert(self->resolver && "Template resolver is not available"); + return *self->resolver; } -clang::ASTContext& CompilationUnit::context() { - return impl->instance->getASTContext(); +clang::ASTContext& CompilationUnitRef::context() { + return self->instance->getASTContext(); } -clang::syntax::TokenBuffer& CompilationUnit::token_buffer() { - return *impl->buffer; +clang::syntax::TokenBuffer& CompilationUnitRef::token_buffer() { + return *self->buffer; +} + +CompilationUnit::~CompilationUnit() { + delete self; } } // namespace clice diff --git a/src/Compiler/CompilationUnitImpl.h b/src/Compiler/CompilationUnitImpl.h deleted file mode 100644 index 8ffa3e6e..00000000 --- a/src/Compiler/CompilationUnitImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "Compiler/CompilationUnit.h" -#include "Compiler/Diagnostic.h" - -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendActions.h" - -namespace clice { - -struct CompilationUnit::Impl { - /// The interested file ID. - clang::FileID interested; - - clang::SourceManager& src_mgr; - - /// The frontend action used to build the unit. - std::unique_ptr action; - - /// Compiler instance, responsible for performing the actual compilation and managing the - /// lifecycle of all objects during the compilation process. - std::unique_ptr instance; - - /// The template resolver used to resolve dependent name. - std::optional resolver; - - /// Token information collected during the preprocessing. - std::optional buffer; - - /// All diretive information collected during the preprocessing. - llvm::DenseMap directives; - - llvm::DenseSet all_files; - - /// Cache for file path. It is used to avoid multiple file path lookup. - llvm::DenseMap path_cache; - - /// Cache for symbol id. - llvm::DenseMap symbol_hash_cache; - - llvm::BumpPtrAllocator path_storage; - - std::shared_ptr> diagnostics; - - std::vector top_level_decls; - - std::chrono::milliseconds build_at; - - std::chrono::milliseconds build_duration; -}; - -} // namespace clice diff --git a/src/Compiler/Diagnostic.cpp b/src/Compiler/Diagnostic.cpp index e54b1099..a091cc07 100644 --- a/src/Compiler/Diagnostic.cpp +++ b/src/Compiler/Diagnostic.cpp @@ -1,6 +1,6 @@ #include "Compiler/Diagnostic.h" -#include "TidyImpl.h" +#include "Implement.h" #include "Support/Format.h" #include "clang/AST/Decl.h" @@ -150,78 +150,72 @@ static DiagnosticLevel diagnostic_level(clang::DiagnosticsEngine::Level level) { } } -/// Get the range for given diagnostic. -/// FIXME: I would like to use `CompilationUnit`. -auto diagnostic_range(const clang::Diagnostic& diagnostic, const clang::LangOptions& options) - -> std::optional> { - /// If location is invalid, it represents the diagnostic is - /// from the command line. - auto location = diagnostic.getLocation(); - if(location.isInvalid()) { - return std::nullopt; - } - - /// If the location is valid, the `SourceManager` is valid too. - auto& src_mgr = diagnostic.getDiags()->getSourceManager(); - - /// Make sure the location is file location. - location = src_mgr.getFileLoc(location); - assert(location.isFileID()); - - auto [fid, offset] = src_mgr.getDecomposedLoc(location); - - /// Select a proper range for the diagnostic. - for(auto range: diagnostic.getRanges()) { - range = clang::Lexer::makeFileCharRange(range, src_mgr, options); - - auto [begin, end] = range.getAsRange(); - auto [begin_fid, begin_offset] = src_mgr.getDecomposedLoc(begin); - if(begin_fid != fid || begin_offset <= offset) { - continue; - } - - auto [end_fid, end_offset] = src_mgr.getDecomposedLoc(end); - if(range.isTokenRange()) { - end_offset += clang::Lexer::MeasureTokenLength(end, src_mgr, options); - } - - if(end_fid == fid && end_offset >= offset) { - return std::pair{ - fid, - LocalSourceRange{begin_offset, end_offset} - }; - } - } - - /// Use token range. - auto end_offset = offset + clang::Lexer::MeasureTokenLength(location, src_mgr, options); - return std::pair{ - fid, - LocalSourceRange{offset, end_offset} - }; -} - -class DiagnosticCollectorImpl : public DiagnosticCollector { +class DiagnosticCollector : public clang::DiagnosticConsumer { public: - DiagnosticCollectorImpl(std::shared_ptr> diagnostics) : - diagnostics(diagnostics) {} + DiagnosticCollector(CompilationUnitRef unit) : unit(unit) {} - void BeginSourceFile(const clang::LangOptions& opts, const clang::Preprocessor* pp) override { - options = &opts; - src_mgr = &pp->getSourceManager(); + auto diagnostic_range(const clang::Diagnostic& diagnostic) + -> std::optional> { + /// If location is invalid, it represents the diagnostic is + /// from the command line. + auto location = diagnostic.getLocation(); + if(location.isInvalid()) { + return std::nullopt; + } + + /// Make sure the location is file location. + location = unit.file_location(location); + assert(location.isFileID()); + + auto [fid, offset] = unit.decompose_location(location); + + /// Select a proper range for the diagnostic. + for(auto range: diagnostic.getRanges()) { + range = clang::Lexer::makeFileCharRange(range, + unit.context().getSourceManager(), + unit.lang_options()); + + auto [begin, end] = range.getAsRange(); + auto [begin_fid, begin_offset] = unit.decompose_location(begin); + if(begin_fid != fid || begin_offset <= offset) { + continue; + } + + auto [end_fid, end_offset] = unit.decompose_location(end); + if(range.isTokenRange()) { + end_offset += unit.token_length(end); + } + + if(end_fid == fid && end_offset >= offset) { + return std::pair{ + fid, + LocalSourceRange{begin_offset, end_offset} + }; + } + } + + /// Use token range. + auto end_offset = offset + unit.token_length(location); + return std::pair{ + fid, + LocalSourceRange{offset, end_offset} + }; } + void BeginSourceFile(const clang::LangOptions&, const clang::Preprocessor*) override {} + void HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& raw_diagnostic) override { - auto& diagnostic = diagnostics->emplace_back(); + auto& diagnostic = unit.diagnostics().emplace_back(); diagnostic.id.value = raw_diagnostic.getID(); if(!is_note(level)) { - if(checker) { - level = checker->adjust_level(level, raw_diagnostic); + if(unit->checker) { + level = unit->checker->adjust_level(level, raw_diagnostic); } } diagnostic.id.level = diagnostic_level(level); + diagnostic.id.source = DiagnosticSource::Clang; /// TODO: // use DiagnosticEngine::SetArgToStringFn to set a custom function to convert arguments to @@ -235,14 +229,14 @@ public: raw_diagnostic.FormatDiagnostic(message); diagnostic.message = message.str(); - if(auto pair = diagnostic_range(raw_diagnostic, *options)) { + if(auto pair = diagnostic_range(raw_diagnostic)) { auto [fid, range] = *pair; diagnostic.fid = fid; diagnostic.range = range; } - if(checker) { - checker->adjust_diag(diagnostic); + if(unit->checker) { + unit->checker->adjust_diag(diagnostic); } /// TODO: handle FixIts @@ -252,14 +246,11 @@ public: void EndSourceFile() override {} private: - std::shared_ptr> diagnostics; - const clang::LangOptions* options; - clang::SourceManager* src_mgr; + CompilationUnitRef unit; }; -std::unique_ptr - Diagnostic::create(std::shared_ptr> diagnostics) { - return std::make_unique(std::move(diagnostics)); +std::unique_ptr create_diagnostic(CompilationUnitRef unit) { + return std::make_unique(unit); } } // namespace clice diff --git a/src/Compiler/Directive.cpp b/src/Compiler/Directive.cpp index 7e7adfd3..d5c01fab 100644 --- a/src/Compiler/Directive.cpp +++ b/src/Compiler/Directive.cpp @@ -1,5 +1,7 @@ #include "Compiler/Directive.h" +#include "Implement.h" + #include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" @@ -262,8 +264,8 @@ private: } // namespace -void Directive::attach(clang::Preprocessor& pp, - llvm::DenseMap& directives) { +void CompilationUnitRef::Self::collect_directives() { + auto& pp = instance->getPreprocessor(); pp.addPPCallbacks(std::make_unique(pp, directives)); } diff --git a/src/Compiler/Implement.h b/src/Compiler/Implement.h new file mode 100644 index 00000000..399386c2 --- /dev/null +++ b/src/Compiler/Implement.h @@ -0,0 +1,137 @@ +#pragma once + +#include "Compiler/CompilationUnit.h" +#include "Compiler/Diagnostic.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang-tidy/ClangTidyCheck.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidyOptions.h" + +namespace clice::tidy { + +using namespace clang::tidy; + +bool is_registered_tidy_check(llvm::StringRef check); + +std::optional is_fast_tidy_check(llvm::StringRef check); + +struct TidyParams {}; + +class ClangTidyChecker; + +/// Configure to run clang-tidy on the given file. +std::unique_ptr configure(clang::CompilerInstance& instance, + const TidyParams& params); + +class ClangTidyChecker { +public: + /// The context of the clang-tidy checker. + ClangTidyContext context; + + /// The instances of checks that are enabled for the current Language. + std::vector> checks; + + /// The match finder to run clang-tidy on ASTs. + clang::ast_matchers::MatchFinder finder; + + ClangTidyChecker(std::unique_ptr provider); + + clang::DiagnosticsEngine::Level adjust_level(clang::DiagnosticsEngine::Level level, + const clang::Diagnostic& diag); + void adjust_diag(Diagnostic& diag); +}; + +} // namespace clice::tidy + +namespace clice { + +constexpr static auto no_hook = [](auto& /*ignore*/) { +}; + +struct CompilationParams; + +struct CompilationUnitRef::Self { + CompilationKind kind; + + CompilationStatus status; + + llvm::StringMap> remapped_buffers; + + /// The frontend action used to build the unit. + std::unique_ptr action; + + /// Compiler instance, responsible for performing the actual compilation and managing the + /// lifecycle of all objects during the compilation process. + std::unique_ptr instance; + + /// The template resolver used to resolve dependent name. + std::optional resolver; + + /// Token information collected during the preprocessing. + std::optional buffer; + + /// All directive information collected during the preprocessing. + llvm::DenseMap directives; + + llvm::DenseSet all_files; + + /// Cache for file path. It is used to avoid multiple file path lookup. + llvm::DenseMap path_cache; + + /// Cache for symbol id. + llvm::DenseMap symbol_hash_cache; + + llvm::BumpPtrAllocator path_storage; + + std::vector diagnostics; + + std::vector top_level_decls; + + std::unique_ptr checker; + + std::chrono::milliseconds build_at; + std::chrono::milliseconds build_duration; + + auto& SM() { + return instance->getSourceManager(); + } + + void collect_directives(); + + void configure_tidy(tidy::TidyParams tidy_params) { + checker = tidy::configure(*instance, tidy_params); + } + + // Must be called before EndSourceFile because the ast context can be destroyed later. + void run_tidy() { + if(checker) { + // AST traversals should exclude the preamble, to avoid performance cliffs. + // TODO: is it okay to affect the unit-level traversal scope here? + auto& Ctx = instance->getASTContext(); + Ctx.setTraversalScope(top_level_decls); + checker->finder.matchAST(Ctx); + + /// XXX: This is messy: clang-tidy checks flush some diagnostics at EOF. + /// However Action->EndSourceFile() would destroy the ASTContext! + /// So just inform the preprocessor of EOF, while keeping everything alive. + instance->getPreprocessor().EndSourceFile(); + } + } + + ~Self() { + if(action) { + // We already notified the pp of end-of-file earlier, so detach it first. + // We must keep it alive until after EndSourceFile(), Sema relies on this. + std::shared_ptr pp = instance->getPreprocessorPtr(); + // Detach so we don't send EOF again + instance->setPreprocessor(nullptr); + action->EndSourceFile(); + } + } +}; + +std::unique_ptr create_diagnostic(CompilationUnitRef unit); + +} // namespace clice diff --git a/src/Compiler/Module.cpp b/src/Compiler/Module.cpp index ca0cb7de..0b736deb 100644 --- a/src/Compiler/Module.cpp +++ b/src/Compiler/Module.cpp @@ -46,10 +46,10 @@ std::string scanModuleName(CompilationParams& params) { if(token.is(clang::tok::hash)) { lexer.LexFromRawLexer(token); - auto diretive = token.getRawIdentifier(); - if(diretive == "if" || diretive == "ifdef" || diretive == "ifndef") { + auto directive = token.getRawIdentifier(); + if(directive == "if" || directive == "ifdef" || directive == "ifndef") { is_in_directive = true; - } else if(diretive == "endif") { + } else if(directive == "endif") { is_in_directive = false; } } else if(token.is(clang::tok::raw_identifier)) { @@ -106,16 +106,15 @@ std::string scanModuleName(CompilationParams& params) { std::expected scanModule(CompilationParams& params) { ModuleInfo info; auto unit = preprocess(params); - if(!unit) { - return std::unexpected(unit.error()); - } + /// FIXME: handle error here. + assert(unit.completed()); - for(auto& import: unit->directives()[unit->interested_file()].imports) { + for(auto& import: unit.directives()[unit.interested_file()].imports) { info.mods.emplace_back(import.name); } - info.isInterfaceUnit = unit->is_module_interface_unit(); - info.name = unit->module_name(); + info.isInterfaceUnit = unit.is_module_interface_unit(); + info.name = unit.module_name(); return info; } diff --git a/src/Compiler/Tidy.cpp b/src/Compiler/Tidy.cpp index cf70ca62..5878f78e 100644 --- a/src/Compiler/Tidy.cpp +++ b/src/Compiler/Tidy.cpp @@ -1,18 +1,4 @@ -//===--- Run clang-tidy ---------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -/// Partial code is copied from clangd. See: -/// 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 "Implement.h" #include "AST/Utility.h" #include "Compiler/Diagnostic.h" #include "Support/Logging.h" diff --git a/src/Compiler/TidyImpl.h b/src/Compiler/TidyImpl.h deleted file mode 100644 index 1255d89f..00000000 --- a/src/Compiler/TidyImpl.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -#include "Compiler/Diagnostic.h" -#include "Compiler/Tidy.h" - -#include "clang-tidy/ClangTidyCheck.h" -#include "clang-tidy/ClangTidyModuleRegistry.h" -#include "clang-tidy/ClangTidyOptions.h" - -namespace clice::tidy { - -using namespace clang::tidy; - -class ClangTidyChecker { -public: - /// The context of the clang-tidy checker. - ClangTidyContext context; - /// The instances of checks that are enabled for the current Language. - std::vector> checks; - /// The match finder to run clang-tidy on ASTs. - clang::ast_matchers::MatchFinder finder; - - ClangTidyChecker(std::unique_ptr provider); - - clang::DiagnosticsEngine::Level adjust_level(clang::DiagnosticsEngine::Level level, - const clang::Diagnostic& diag); - void adjust_diag(Diagnostic& diag); -}; - -} // namespace clice::tidy diff --git a/src/Feature/CodeCompletion.cpp b/src/Feature/CodeCompletion.cpp index 060b3a8b..c901e114 100644 --- a/src/Feature/CodeCompletion.cpp +++ b/src/Feature/CodeCompletion.cpp @@ -432,7 +432,8 @@ std::vector code_complete(CompilationParams& params, auto& [file, offset] = params.completion; auto consumer = new CodeCompletionCollector(offset, items, option); - if(auto info = complete(params, consumer)) { + auto unit = complete(params, consumer); + if(!unit.completed()) { /// TODO: Handle error here. } diff --git a/src/Feature/Diagnostic.cpp b/src/Feature/Diagnostic.cpp index f9fa9b7c..a8535d6b 100644 --- a/src/Feature/Diagnostic.cpp +++ b/src/Feature/Diagnostic.cpp @@ -6,7 +6,7 @@ namespace clice::feature { -json::Value diagnostics(PositionEncodingKind kind, PathMapping mapping, CompilationUnit& unit) { +json::Value diagnostics(PositionEncodingKind kind, PathMapping mapping, CompilationUnitRef unit) { json::Array result; std::optional diagnostic; diff --git a/src/Feature/DocumentLink.cpp b/src/Feature/DocumentLink.cpp index 1babe95d..e4455aab 100644 --- a/src/Feature/DocumentLink.cpp +++ b/src/Feature/DocumentLink.cpp @@ -8,7 +8,7 @@ namespace clice::feature { namespace {} -DocumentLinks document_links(CompilationUnit& unit) { +DocumentLinks document_links(CompilationUnitRef unit) { DocumentLinks links; auto& interested_diretive = unit.directives()[unit.interested_file()]; @@ -39,7 +39,7 @@ DocumentLinks document_links(CompilationUnit& unit) { return links; } -index::Shared index_document_link(CompilationUnit& unit) { +index::Shared index_document_link(CompilationUnitRef unit) { index::Shared result; for(auto& [fid, diretives]: unit.directives()) { diff --git a/src/Feature/DocumentSymbol.cpp b/src/Feature/DocumentSymbol.cpp index dba76de4..ea92f350 100644 --- a/src/Feature/DocumentSymbol.cpp +++ b/src/Feature/DocumentSymbol.cpp @@ -50,7 +50,7 @@ class DocumentSymbolCollector : public FilteredASTVisitor; - DocumentSymbolCollector(CompilationUnit& unit, bool interested_only) : + DocumentSymbolCollector(CompilationUnitRef unit, bool interested_only) : Base(unit, interested_only) {} bool is_interested(clang::Decl* decl) { @@ -126,7 +126,7 @@ public: } // namespace -DocumentSymbols document_symbols(CompilationUnit& unit) { +DocumentSymbols document_symbols(CompilationUnitRef unit) { DocumentSymbolCollector collector(unit, true); collector.TraverseDecl(unit.tu()); @@ -135,7 +135,7 @@ DocumentSymbols document_symbols(CompilationUnit& unit) { return std::move(frame.symbols); } -index::Shared index_document_symbol(CompilationUnit& unit) { +index::Shared index_document_symbol(CompilationUnitRef unit) { DocumentSymbolCollector collector(unit, true); collector.TraverseDecl(unit.tu()); diff --git a/src/Feature/FoldingRange.cpp b/src/Feature/FoldingRange.cpp index 3766a39b..7f9de60b 100644 --- a/src/Feature/FoldingRange.cpp +++ b/src/Feature/FoldingRange.cpp @@ -10,7 +10,7 @@ namespace { class FoldingRangeCollector : public FilteredASTVisitor { public: - FoldingRangeCollector(CompilationUnit& unit, bool interested_only) : + FoldingRangeCollector(CompilationUnitRef unit, bool interested_only) : FilteredASTVisitor(unit, interested_only) {} constexpr static auto LastColOfLine = std::numeric_limits::max(); @@ -145,14 +145,14 @@ public: return true; } - auto build_for_file(CompilationUnit& unit) { + auto build_for_file(CompilationUnitRef unit) { TraverseDecl(unit.tu()); collect_drectives(unit.directives()[unit.interested_file()]); std::ranges::sort(result, refl::less); return std::move(result); } - auto build_for_index(CompilationUnit& unit) { + auto build_for_index(CompilationUnitRef unit) { TraverseDecl(unit.tu()); for(auto& [fid, directive]: unit.directives()) { collect_drectives(directive); @@ -326,11 +326,11 @@ private: } // namespace -FoldingRanges folding_ranges(CompilationUnit& unit) { +FoldingRanges folding_ranges(CompilationUnitRef unit) { return FoldingRangeCollector(unit, true).build_for_file(unit); } -index::Shared index_folding_range(CompilationUnit& unit) { +index::Shared index_folding_range(CompilationUnitRef unit) { return FoldingRangeCollector(unit, false).build_for_index(unit); } // namespace feature diff --git a/src/Feature/Hover.cpp b/src/Feature/Hover.cpp index 80437859..9ce2e3c4 100644 --- a/src/Feature/Hover.cpp +++ b/src/Feature/Hover.cpp @@ -12,7 +12,7 @@ namespace clice::feature { namespace { -std::vector getHoverItems(CompilationUnit& unit, const clang::NamedDecl* decl) { +std::vector getHoverItems(CompilationUnitRef unit, const clang::NamedDecl* decl) { clang::ASTContext& Ctx = unit.context(); std::vector items; @@ -35,7 +35,7 @@ std::vector getHoverItems(CompilationUnit& unit, const clang::NamedDe return items; } -std::string getDocument(CompilationUnit& unit, const clang::NamedDecl* decl) { +std::string getDocument(CompilationUnitRef unit, const clang::NamedDecl* decl) { clang::ASTContext& Ctx = unit.context(); const clang::RawComment* comment = Ctx.getRawCommentForAnyRedecl(decl); if(!comment) { @@ -45,14 +45,14 @@ std::string getDocument(CompilationUnit& unit, const clang::NamedDecl* decl) { return comment->getRawText(Ctx.getSourceManager()).str(); } -std::string getQualifier(CompilationUnit& unit, const clang::NamedDecl* decl) { +std::string getQualifier(CompilationUnitRef unit, const clang::NamedDecl* decl) { std::string result; llvm::raw_string_ostream os(result); decl->printNestedNameSpecifier(os); return result; } -std::string getSourceCode(CompilationUnit& unit, const clang::NamedDecl* decl) { +std::string getSourceCode(CompilationUnitRef unit, const clang::NamedDecl* decl) { clang::SourceRange range = decl->getSourceRange(); // auto& TB = unit.tokBuf(); // auto& SM = unit.srcMgr(); @@ -63,7 +63,7 @@ std::string getSourceCode(CompilationUnit& unit, const clang::NamedDecl* decl) { } // namespace -Hover hover(CompilationUnit& unit, const clang::NamedDecl* decl) { +Hover hover(CompilationUnitRef unit, const clang::NamedDecl* decl) { return Hover{ .kind = SymbolKind::from(decl), .name = ast::name_of(decl), @@ -74,7 +74,7 @@ Hover hover(CompilationUnit& unit, const clang::NamedDecl* decl) { }; } -Hover hover(CompilationUnit& unit, std::uint32_t offset) { +Hover hover(CompilationUnitRef unit, std::uint32_t offset) { Hover info; auto tree = SelectionTree::create_right(unit, {offset, offset}); diff --git a/src/Feature/InlayHint.cpp b/src/Feature/InlayHint.cpp index cda300d6..66482e3f 100644 --- a/src/Feature/InlayHint.cpp +++ b/src/Feature/InlayHint.cpp @@ -97,7 +97,7 @@ struct Callee { class Builder { public: Builder(std::vector& result, - CompilationUnit& unit, + CompilationUnitRef unit, LocalSourceRange restrict_range, const config::InlayHintsOptions& options) : result(result), unit(unit), restrict_range(restrict_range), options(options), @@ -523,7 +523,7 @@ public: private: std::vector& result; - CompilationUnit& unit; + CompilationUnitRef unit; LocalSourceRange restrict_range; const config::InlayHintsOptions& options; clang::PrintingPolicy policy; @@ -534,7 +534,7 @@ public: using Base = FilteredASTVisitor; Visitor(Builder& builder, - CompilationUnit& unit, + CompilationUnitRef unit, std::optional restrict_range, const config::InlayHintsOptions& options) : Base(unit, true), builder(builder), unit(unit), options(options) {} @@ -867,7 +867,7 @@ public: private: Builder& builder; - CompilationUnit& unit; + CompilationUnitRef unit; const config::InlayHintsOptions& options; // If/else chains are tricky. @@ -881,7 +881,7 @@ private: } // namespace -auto inlay_hints(CompilationUnit& unit, +auto inlay_hints(CompilationUnitRef unit, LocalSourceRange target, const config::InlayHintsOptions& options) -> std::vector { std::vector hints; diff --git a/src/Feature/SemanticToken.cpp b/src/Feature/SemanticToken.cpp index 8ad4625b..53c02876 100644 --- a/src/Feature/SemanticToken.cpp +++ b/src/Feature/SemanticToken.cpp @@ -246,7 +246,7 @@ public: } // namespace -SemanticTokens semantic_tokens(CompilationUnit& unit) { +SemanticTokens semantic_tokens(CompilationUnitRef unit) { SemanticTokensCollector collector(unit, true); collector.highlight(unit.interested_file()); collector.run(); @@ -254,7 +254,7 @@ SemanticTokens semantic_tokens(CompilationUnit& unit) { return std::move(collector.result); } -index::Shared index_semantic_token(CompilationUnit& unit) { +index::Shared index_semantic_token(CompilationUnitRef unit) { SemanticTokensCollector collector(unit, false); for(auto fid: unit.files()) { collector.highlight(fid); diff --git a/src/Feature/SignatureHelp.cpp b/src/Feature/SignatureHelp.cpp index bc9327ed..adbfdfcc 100644 --- a/src/Feature/SignatureHelp.cpp +++ b/src/Feature/SignatureHelp.cpp @@ -203,7 +203,8 @@ proto::SignatureHelp signature_help(CompilationParams& params, complete_options.IncludeFixIts = false; auto consumer = new Collector(help, complete_options); - if(auto info = complete(params, consumer)) { + auto unit = complete(params, consumer); + if(!unit.completed()) { /// FIXME: do something. } return help; diff --git a/src/Index/IncludeGraph.cpp b/src/Index/IncludeGraph.cpp index 6d9f9420..c8eddb52 100644 --- a/src/Index/IncludeGraph.cpp +++ b/src/Index/IncludeGraph.cpp @@ -4,7 +4,7 @@ namespace clice::index { -static std::uint32_t addIncludeChain(CompilationUnit& unit, +static std::uint32_t addIncludeChain(CompilationUnitRef unit, clang::FileID fid, IncludeGraph& graph, llvm::StringMap& path_table) { @@ -45,7 +45,7 @@ static std::uint32_t addIncludeChain(CompilationUnit& unit, return index; } -IncludeGraph IncludeGraph::from(CompilationUnit& unit) { +IncludeGraph IncludeGraph::from(CompilationUnitRef unit) { llvm::StringMap path_table; IncludeGraph graph; for(auto fid: unit.files()) { diff --git a/src/Index/TUIndex.cpp b/src/Index/TUIndex.cpp index aea7ef28..ee3f9b61 100644 --- a/src/Index/TUIndex.cpp +++ b/src/Index/TUIndex.cpp @@ -11,7 +11,7 @@ namespace { class Builder : public SemanticVisitor { public: - Builder(TUIndex& result, CompilationUnit& unit) : + Builder(TUIndex& result, CompilationUnitRef unit) : SemanticVisitor(unit, false), result(result) { result.graph = IncludeGraph::from(unit); } @@ -75,24 +75,29 @@ public: RelationKind kind, const clang::NamedDecl* target, clang::SourceRange range) { - auto [fid, relationRange] = unit.decompose_expansion_range(range); + auto [fid, relation_range] = unit.decompose_expansion_range(range); Relation relation{.kind = kind}; if(kind.isDeclOrDef()) { - auto [fid2, definition_range] = unit.decompose_expansion_range(decl->getSourceRange()); - assert(fid == fid2 && "Invalid definition location"); - relation.range = relationRange; - relation.set_definition_range(definition_range); + relation.range = relation_range; + /// FIXME: why definition or declaration has invalid source range? implicit node? + auto source_range = decl->getSourceRange(); + if(source_range.isValid()) { + auto [fid2, definition_range] = + unit.decompose_expansion_range(decl->getSourceRange()); + assert(fid == fid2 && "Invalid definition location"); + relation.set_definition_range(definition_range); + } } else if(kind.isReference()) { - relation.range = relationRange; + relation.range = relation_range; relation.target_symbol = 0; } else if(kind.isBetweenSymbol()) { auto symbol_id = unit.getSymbolID(ast::normalize(target)); relation.target_symbol = symbol_id.hash; } else if(kind.isCall()) { auto symbol_id = unit.getSymbolID(ast::normalize(target)); - relation.range = relationRange; + relation.range = relation_range; relation.target_symbol = symbol_id.hash; } else { std::unreachable(); @@ -161,7 +166,7 @@ std::array FileIndex::hash() { return hasher.final(); } -TUIndex TUIndex::build(CompilationUnit& unit) { +TUIndex TUIndex::build(CompilationUnitRef unit) { TUIndex index; index.built_at = unit.build_at(); diff --git a/src/Index/USRGeneration.cpp b/src/Index/USRGeneration.cpp index a041f70f..4e026500 100644 --- a/src/Index/USRGeneration.cpp +++ b/src/Index/USRGeneration.cpp @@ -785,7 +785,10 @@ void USRGenerator::VisitTemplateParameterList(const TemplateParameterList* Param if(p->isParameterPack()) Out << 'p'; Out << 'T'; - if(p->hasTypeConstraint()) { + + /// FIXME: workaround figure out why `p->hasTypeConstraint()` is true but + /// `p->getTypeConstraint() is empty`. + if(p->hasTypeConstraint() && p->getTypeConstraint()) { Out << ":TC"; AppendExprODRHash(p->getTypeConstraint()->getImmediatelyDeclaredConstraint(), Out); } diff --git a/src/Server/Document.cpp b/src/Server/Document.cpp index b26f7a01..07540a4c 100644 --- a/src/Server/Document.cpp +++ b/src/Server/Document.cpp @@ -176,8 +176,7 @@ async::Task build_pch_task(CompilationContext& info, std::shared_ptr open_file, std::string path, std::uint32_t bound, - std::string content, - std::shared_ptr> diagnostics) { + std::string content) { if(!fs::exists(cache_dir)) { auto error = fs::create_directories(cache_dir); if(error) { @@ -186,15 +185,11 @@ async::Task build_pch_task(CompilationContext& info, } } - /// Everytime we build a new pch, the old diagnostics should be discarded. - diagnostics->clear(); - CompilationParams params; - params.kind = CompilationUnit::Preamble; + params.kind = CompilationKind::Preamble; params.output_file = path::join(cache_dir, path::filename(path) + ".pch"); params.arguments_from_database = true; params.arguments = std::move(info.arguments); - params.diagnostics = diagnostics; params.add_remapped_file(path, content, bound); std::string command; @@ -210,24 +205,25 @@ async::Task build_pch_task(CompilationContext& info, std::string message = std::move(command); // reuse buffer std::vector links; - bool success = co_await async::submit([¶ms, &pch, &message, &links] -> bool { + bool success = co_await async::submit([¶ms, &pch, &message, &links, &path] -> bool { /// PCH file is written until destructing, Add a single block for it. auto unit = compile(params, pch); - if(!unit) { - message = std::move(unit.error()); + if(!unit.completed()) { + /// FIXME: use `feature::diagnostic` to flush diagnostic for reporting. + /// LOG_WARN("Building PCH fails for {}, Because: {}", path, message); + for(auto& diagnostic: unit.diagnostics()) { + LOG_WARN("{}", diagnostic.message); + } + return false; } - links = feature::document_links(*unit); + links = feature::document_links(unit); /// TODO: index PCH file, etc return true; }); if(!success) { - LOG_WARN("Building PCH fails for {}, Because: {}", path, message); - for(auto& diagnostic: *diagnostics) { - LOG_WARN("{}", diagnostic.message); - } co_return false; } @@ -276,13 +272,8 @@ async::Task Server::build_pch(std::string file, std::string content) { } /// Schedule the new building task. - task = build_pch_task(info, - config.project.cache_dir, - open_file, - file, - bound, - std::move(content), - open_file->diagnostics); + task = + build_pch_task(info, config.project.cache_dir, open_file, file, bound, std::move(content)); if(co_await task) { /// FIXME: At this point, task has already been finished, destroy it directly. task.release().destroy(); @@ -316,29 +307,27 @@ async::Task<> Server::build_ast(std::string path, std::string content) { options.query_toolchain = true; CompilationParams params; - params.kind = CompilationUnit::Content; + params.kind = CompilationKind::Content; params.arguments_from_database = true; params.arguments = database.lookup(path, options).arguments; params.add_remapped_file(path, content); params.pch = {pch->path, pch->preamble.size()}; - file->diagnostics->clear(); - params.diagnostics = file->diagnostics; params.clang_tidy = config.project.clang_tidy; /// Check result - auto ast = co_await async::submit([&] { return compile(params); }); - if(!ast) { + auto unit = co_await async::submit([&] { return compile(params); }); + if(!unit.completed()) { /// FIXME: Fails needs cancel waiting tasks. - LOG_ERROR("Building AST fails for {}, Beacuse: {}", path, ast.error()); - for(auto& diagnostic: *file->diagnostics) { - LOG_ERROR("{}", diagnostic.message); - } + /// LOG_ERROR("Building AST fails for {}, Beacuse: {}", path, unit.error()); + /// for(auto& diagnostic: unit.diagnostics()) { + /// LOG_ERROR("{}", diagnostic.message); + /// } co_return; } /// Send diagnostics auto diagnostics = co_await async::submit( - [&, kind = this->kind] { return feature::diagnostics(kind, mapping, *ast); }); + [&, kind = this->kind] { return feature::diagnostics(kind, mapping, unit); }); co_await notify("textDocument/publishDiagnostics", json::Object{ {"uri", mapping.to_uri(path) }, @@ -349,7 +338,7 @@ async::Task<> Server::build_ast(std::string path, std::string content) { /// co_await indexer.index(*ast); /// Update built AST info. - file->ast = std::make_shared(std::move(*ast)); + file->ast = std::make_shared(std::move(unit)); /// Dispose the task so that it will destroyed when task complete. file->ast_build_task.dispose(); diff --git a/src/Server/Feature.cpp b/src/Server/Feature.cpp index b8efafbe..98df9fa2 100644 --- a/src/Server/Feature.cpp +++ b/src/Server/Feature.cpp @@ -30,7 +30,7 @@ auto Server::on_completion(proto::CompletionParams params) -> Result { /// Set compilation params ... . CompilationParams params; - params.kind = CompilationUnit::Completion; + params.kind = CompilationKind::Completion; params.arguments_from_database = true; params.arguments = database.lookup(path).arguments; params.add_remapped_file(path, content); @@ -88,7 +88,7 @@ async::Task Server::on_signature_help(proto::SignatureHelpParams pa /// Set compilation params ... . CompilationParams params; - params.kind = CompilationUnit::Completion; + params.kind = CompilationKind::Completion; params.arguments_from_database = true; params.arguments = database.lookup(path, options).arguments; params.add_remapped_file(path, content); diff --git a/src/Server/Indexer.cpp b/src/Server/Indexer.cpp index cfd78340..ad4dbd28 100644 --- a/src/Server/Indexer.cpp +++ b/src/Server/Indexer.cpp @@ -9,9 +9,9 @@ namespace clice { async::Task<> Indexer::index(llvm::StringRef path) { CompilationParams params; - params.kind = CompilationUnit::Indexing; + params.kind = CompilationKind::Indexing; params.arguments_from_database = true; - params.arguments = database.lookup(path).arguments; + params.arguments = database.lookup(path, {.query_toolchain = true}).arguments; auto path_id = project_index.path_pool.path_id(path); auto& merged_index = get_index(path_id); @@ -25,12 +25,12 @@ async::Task<> Indexer::index(llvm::StringRef path) { auto tu_index = co_await async::submit([&]() -> std::optional { auto unit = compile(params); - if(!unit) { - LOG_INFO("Fail to index for {}, because: {}", path, unit.error()); + if(!unit.completed()) { + /// LOG_INFO("Fail to index for {}, because: {}", path, unit.error()); return std::nullopt; } - return index::TUIndex::build(*unit); + return index::TUIndex::build(unit); }); if(!tu_index) { diff --git a/tests/unit/AST/ResolverTests.cpp b/tests/unit/AST/ResolverTests.cpp index 83c6eb0b..763d398b 100644 --- a/tests/unit/AST/ResolverTests.cpp +++ b/tests/unit/AST/ResolverTests.cpp @@ -8,13 +8,13 @@ namespace clice::testing { namespace { struct InputFinder : clang::RecursiveASTVisitor { - CompilationUnit& unit; + CompilationUnitRef unit; clang::QualType input; clang::QualType expect; using Base = clang::RecursiveASTVisitor; - InputFinder(CompilationUnit& unit) : unit(unit) {} + InputFinder(CompilationUnitRef unit) : unit(unit) {} bool TraverseDecl(clang::Decl* decl) { if(decl && (llvm::isa(decl) || diff --git a/tests/unit/Compiler/DiagnosticTests.cpp b/tests/unit/Compiler/DiagnosticTests.cpp index 3daa1189..965a43bf 100644 --- a/tests/unit/Compiler/DiagnosticTests.cpp +++ b/tests/unit/Compiler/DiagnosticTests.cpp @@ -80,28 +80,59 @@ using namespace clice; TEST_SUITE(Diagnostic) { -TEST_CASE(CommandError) { +TEST_CASE(TargetError) { CompilationParams params; - /// miss input file. - params.arguments = {"clang++"}; - params.add_remapped_file("main.cpp", "int main() { return 0; }"); + params.arguments = {"clang++", "-target", "aa-bb-cc", "main.cpp"}; + params.add_remapped_file("main.cpp", ""); + auto unit = compile(params); - ASSERT_FALSE(unit.has_value()); + ASSERT_TRUE(unit.setup_fail()); + ASSERT_TRUE(unit.diagnostics().size() == 1); + + auto& diag = unit.diagnostics()[0]; + EXPECT_EQ(diag.id.diagnostic_code(), "err_target_unknown_triple"); + EXPECT_EQ(diag.id.level, DiagnosticLevel::Error); + EXPECT_EQ(diag.id.source, DiagnosticSource::Clang); + EXPECT_TRUE(diag.fid.isInvalid()); + EXPECT_TRUE(!diag.range.valid()); + EXPECT_EQ(diag.message, "unknown target triple 'aa-bb-cc'"); } TEST_CASE(Error) { CompilationParams params; params.arguments = {"clang++", "main.cpp"}; params.add_remapped_file("main.cpp", "int main() { return 0 }"); - auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); - ASSERT_FALSE(unit->diagnostics().empty()); - /// for(auto& diag: unit->diagnostics()) { - /// std::println("{}", diag.message); - /// } + auto unit = compile(params); + ASSERT_TRUE(unit.completed()); + ASSERT_TRUE(unit.diagnostics().size() == 1); + + auto& diag = unit.diagnostics()[0]; + EXPECT_EQ(diag.id.diagnostic_code(), "err_expected_semi_after_stmt"); + EXPECT_EQ(diag.id.level, DiagnosticLevel::Error); + EXPECT_EQ(diag.id.source, DiagnosticSource::Clang); + EXPECT_EQ(diag.fid, unit.interested_file()); + EXPECT_TRUE(diag.range.valid()); + EXPECT_EQ(diag.message, "expected ';' after return statement"); }; +TEST_CASE(Warning) { + CompilationParams params; + params.arguments = {"clang++", "-Wall", "-Wunused-variable", "main.cpp"}; + params.add_remapped_file("main.cpp", "int main() { int x; return 0; }"); + + auto unit = compile(params); + ASSERT_TRUE(unit.completed()); + ASSERT_EQ(unit.diagnostics().size(), 1); + + auto& diag = unit.diagnostics()[0]; + EXPECT_EQ(diag.id.diagnostic_code(), "warn_unused_variable"); + EXPECT_EQ(diag.id.level, DiagnosticLevel::Warning); + EXPECT_EQ(diag.id.source, DiagnosticSource::Clang); + EXPECT_TRUE(diag.range.valid()); + EXPECT_TRUE(diag.message.find("unused variable") != std::string::npos); +} + TEST_CASE(PCHError) { /// Any error in compilation will result in failure on generating PCH or PCM. CompilationParams params; @@ -114,7 +145,7 @@ void foo() {} PCHInfo info; auto unit = compile(params, info); - ASSERT_FALSE(unit.has_value()); + ASSERT_TRUE(unit.fatal_error()); } TEST_CASE(ASTError) { @@ -128,7 +159,7 @@ void foo() {} PCHInfo info; auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); + ASSERT_TRUE(unit.completed()); } }; // TEST_SUITE(Diagnostic) diff --git a/tests/unit/Compiler/ModuleTests.cpp b/tests/unit/Compiler/ModuleTests.cpp index fddb64ca..59ade193 100644 --- a/tests/unit/Compiler/ModuleTests.cpp +++ b/tests/unit/Compiler/ModuleTests.cpp @@ -27,7 +27,7 @@ auto buildPCM = [](llvm::StringRef file, llvm::StringRef code) { params.add_remapped_file("./test.h", "export int foo2();"); PCMInfo pcm; - if(!compile(params, pcm)) { + if(!compile(params, pcm).completed()) { llvm::errs() << "Failed to build PCM\n"; std::abort(); } diff --git a/tests/unit/Compiler/PreambleTests.cpp b/tests/unit/Compiler/PreambleTests.cpp index 3483a097..d8ad26d6 100644 --- a/tests/unit/Compiler/PreambleTests.cpp +++ b/tests/unit/Compiler/PreambleTests.cpp @@ -68,7 +68,7 @@ void expect_build_pch(llvm::StringRef main_file, { /// NOTE: PCH file is written when CompilerInstance is destructed. auto unit = compile(params, info); - ASSERT_TRUE(unit.has_value()); + ASSERT_TRUE(unit.completed()); ASSERT_EQ(info.path, output_path); /// expect(that % info.command == params.arguments); @@ -83,7 +83,7 @@ void expect_build_pch(llvm::StringRef main_file, params.add_remapped_file(main_file, content); params.pch = {info.path, info.preamble.size()}; auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); + ASSERT_TRUE(unit.completed()); }; TEST_CASE(Bounds) { @@ -184,16 +184,16 @@ int foo(); } auto unit = preprocess(params); - ASSERT_TRUE(unit.has_value()); + ASSERT_TRUE(unit.completed()); auto path = path::join(".", "test1.h"); - auto fid = unit->file_id(path); + auto fid = unit.file_id(path); ASSERT_TRUE(fid.isValid()); while(fid.isValid()) { - auto location = unit->include_location(fid); - auto [fid2, offset] = unit->decompose_location(location); - auto content = unit->file_content(fid2).substr(0, offset); + auto location = unit.include_location(fid); + auto [fid2, offset] = unit.decompose_location(location); + auto content = unit.file_content(fid2).substr(0, offset); /// Remove incomplete include. content = content.substr(0, content.rfind("\n")); @@ -253,7 +253,7 @@ int y = foo(); { auto unit = compile(params, info); - ASSERT_TRUE(unit.has_value()); + ASSERT_TRUE(unit.completed()); ASSERT_EQ(info.path, outPath); /// expect(that % info.command == params.arguments); @@ -268,7 +268,7 @@ int y = foo(); params.add_remapped_file("main.cpp", content); params.pch = {info.path, last_bound}; auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); + ASSERT_TRUE(unit.completed()); }; TEST_CASE(Scan) { diff --git a/tests/unit/Compiler/TidyTests.cpp b/tests/unit/Compiler/TidyTests.cpp index 1fadf925..b037d365 100644 --- a/tests/unit/Compiler/TidyTests.cpp +++ b/tests/unit/Compiler/TidyTests.cpp @@ -1,6 +1,5 @@ #include "Test/Test.h" #include "Compiler/Compilation.h" -#include "Compiler/Tidy.h" namespace clice::testing { namespace { @@ -8,13 +7,13 @@ namespace { TEST_SUITE(ClangTidy) { TEST_CASE(FastCheck) { - ASSERT_TRUE(tidy::is_fast_tidy_check("readability-misleading-indentation")); - ASSERT_TRUE(tidy::is_fast_tidy_check("bugprone-unused-return-value")); - - // clangd/unittests/TidyProviderTests.cpp - ASSERT_TRUE(tidy::is_fast_tidy_check("misc-const-correctness")); - ASSERT_TRUE(tidy::is_fast_tidy_check("bugprone-suspicious-include")); - ASSERT_EQ(tidy::is_fast_tidy_check("replay-preamble-check"), std::nullopt); + // ASSERT_TRUE(tidy::is_fast_tidy_check("readability-misleading-indentation")); + // ASSERT_TRUE(tidy::is_fast_tidy_check("bugprone-unused-return-value")); + // + // // clangd/unittests/TidyProviderTests.cpp + // ASSERT_TRUE(tidy::is_fast_tidy_check("misc-const-correctness")); + // ASSERT_TRUE(tidy::is_fast_tidy_check("bugprone-suspicious-include")); + // ASSERT_EQ(tidy::is_fast_tidy_check("replay-preamble-check"), std::nullopt); } TEST_CASE(Tidy) { @@ -23,8 +22,8 @@ TEST_CASE(Tidy) { params.arguments = {"clang++", "main.cpp"}; params.add_remapped_file("main.cpp", "int main() { return 0 }"); auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); - ASSERT_FALSE(unit->diagnostics().empty()); + ASSERT_TRUE(unit.completed()); + ASSERT_FALSE(unit.diagnostics().empty()); } }; // TEST_SUITE(ClangTidy) diff --git a/tests/unit/Compiler/ToolchainTests.cpp b/tests/unit/Compiler/ToolchainTests.cpp index c7e5d4cc..3afcc373 100644 --- a/tests/unit/Compiler/ToolchainTests.cpp +++ b/tests/unit/Compiler/ToolchainTests.cpp @@ -73,8 +73,8 @@ TEST_CASE(GCC, {.skip = !(CIEnvironment && (Windows || Linux))}) { )"); auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); - ASSERT_TRUE(unit->diagnostics().empty()); + ASSERT_TRUE(unit.completed()); + ASSERT_TRUE(unit.diagnostics().empty()); }; TEST_CASE(MSVC, {.skip = !CIEnvironment}) { @@ -112,8 +112,8 @@ TEST_CASE(Clang, {.skip = !CIEnvironment}) { )"); auto unit = compile(params); - ASSERT_TRUE(unit.has_value()); - ASSERT_TRUE(unit->diagnostics().empty()); + ASSERT_TRUE(unit.completed()); + ASSERT_TRUE(unit.diagnostics().empty()); }; TEST_CASE(Zig, {.skip = !CIEnvironment}) { diff --git a/tests/unit/Test/Tester.cpp b/tests/unit/Test/Tester.cpp index b819cd6d..608ce8fa 100644 --- a/tests/unit/Test/Tester.cpp +++ b/tests/unit/Test/Tester.cpp @@ -6,7 +6,7 @@ void Tester::prepare(llvm::StringRef standard) { auto command = std::format("clang++ {} {} -fms-extensions", standard, src_path); database.add_command("fake", src_path, command); - params.kind = CompilationUnit::Content; + params.kind = CompilationKind::Content; CommandOptions options; options.resource_dir = true; @@ -31,24 +31,22 @@ bool Tester::compile(llvm::StringRef standard) { prepare(standard); auto unit = clice::compile(params); - if(!unit) { - LOG_ERROR("{}", unit.error()); - for(auto& diag: *params.diagnostics) { + if(!unit.completed()) { + for(auto& diag: unit.diagnostics()) { LOG_ERROR("{}", diag.message); } return false; } - this->unit.emplace(std::move(*unit)); + this->unit.emplace(std::move(unit)); return true; } bool Tester::compile_with_pch(llvm::StringRef standard) { - params.diagnostics = std::make_shared>(); auto command = std::format("clang++ {} {} -fms-extensions", standard, src_path); database.add_command("fake", src_path, command); - params.kind = CompilationUnit::Preamble; + params.kind = CompilationKind::Preamble; CommandOptions options; options.resource_dir = true; @@ -80,9 +78,8 @@ bool Tester::compile_with_pch(llvm::StringRef standard) { PCHInfo info; { auto unit = clice::compile(params, info); - if(!unit) { - LOG_ERROR("{}", unit.error()); - for(auto& diag: *params.diagnostics) { + if(!unit.completed()) { + for(auto& diag: unit.diagnostics()) { LOG_ERROR("{}", diag.message); } return false; @@ -91,7 +88,7 @@ bool Tester::compile_with_pch(llvm::StringRef standard) { /// Build AST params.output_file.clear(); - params.kind = CompilationUnit::Content; + params.kind = CompilationKind::Content; params.pch = {info.path, info.preamble.size()}; for(auto& [file, source]: sources.all_files) { if(file == src_path) { @@ -104,15 +101,14 @@ bool Tester::compile_with_pch(llvm::StringRef standard) { } auto unit = clice::compile(params); - if(!unit) { - LOG_ERROR("{}", unit.error()); - for(auto& diag: *params.diagnostics) { + if(!unit.completed()) { + for(auto& diag: unit.diagnostics()) { LOG_ERROR("{}", diag.message); } return false; } - this->unit.emplace(std::move(*unit)); + this->unit.emplace(std::move(unit)); return true; }