[NFC] [clangd] [C++20] [Modules] Introduce ProjectModules::getModuleNameState interface (#193133)
A hole in the current design is that, we assumed there is no duplicated module name in different module interface in the same project. This is not true techniquelly. ISO disallows duplicated module names in a linked program. But we can have multiple program in a project. It will be fine if they are not linked together. And in practice, it will be fine if the symbols are masked and if these module interface units are not showing in the same context of a single translation unit. I am trying to improve this. This patch tries to add some NFC things to reduce further patch size. AI assisted.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
//===------------------ ProjectModules.cpp -------------------------*-
|
||||
//C++-*-===//
|
||||
//===------------------ ProjectModules.cpp --------- ------------*- C++-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -14,6 +13,26 @@
|
||||
|
||||
namespace clang::clangd {
|
||||
namespace {
|
||||
|
||||
std::optional<tooling::CompileCommand>
|
||||
getCompileCommandForFile(const clang::tooling::CompilationDatabase &CDB,
|
||||
PathRef FilePath,
|
||||
const ProjectModules::CommandMangler &Mangler) {
|
||||
auto Candidates = CDB.getCompileCommands(FilePath);
|
||||
if (Candidates.empty())
|
||||
return std::nullopt;
|
||||
|
||||
// Choose the first candidates as the compile commands as the file.
|
||||
// Following the same logic with
|
||||
// DirectoryBasedGlobalCompilationDatabase::getCompileCommand.
|
||||
tooling::CompileCommand Cmd = std::move(Candidates.front());
|
||||
|
||||
if (Mangler)
|
||||
Mangler(Cmd, FilePath);
|
||||
|
||||
return Cmd;
|
||||
}
|
||||
|
||||
/// A scanner to query the dependency information for C++20 Modules.
|
||||
///
|
||||
/// The scanner can scan a single file with `scan(PathRef)` member function
|
||||
@@ -96,18 +115,10 @@ private:
|
||||
std::optional<ModuleDependencyScanner::ModuleDependencyInfo>
|
||||
ModuleDependencyScanner::scan(PathRef FilePath,
|
||||
const ProjectModules::CommandMangler &Mangler) {
|
||||
auto Candidates = CDB->getCompileCommands(FilePath);
|
||||
if (Candidates.empty())
|
||||
auto Cmd = getCompileCommandForFile(*CDB, FilePath, Mangler);
|
||||
if (!Cmd)
|
||||
return std::nullopt;
|
||||
|
||||
// Choose the first candidates as the compile commands as the file.
|
||||
// Following the same logic with
|
||||
// DirectoryBasedGlobalCompilationDatabase::getCompileCommand.
|
||||
tooling::CompileCommand Cmd = std::move(Candidates.front());
|
||||
|
||||
if (Mangler)
|
||||
Mangler(Cmd, FilePath);
|
||||
|
||||
using namespace clang::tooling;
|
||||
|
||||
DependencyScanningTool ScanningTool(Service);
|
||||
@@ -119,13 +130,13 @@ ModuleDependencyScanner::scan(PathRef FilePath,
|
||||
TextDiagnosticPrinter DiagConsumer(OS, DiagOpts);
|
||||
|
||||
std::optional<P1689Rule> ScanningResult =
|
||||
ScanningTool.getP1689ModuleDependencyFile(Cmd, Cmd.Directory,
|
||||
ScanningTool.getP1689ModuleDependencyFile(*Cmd, Cmd->Directory,
|
||||
DiagConsumer);
|
||||
|
||||
if (!ScanningResult) {
|
||||
elog("Scanning modules dependencies for {0} failed: {1}", FilePath, S);
|
||||
std::string Cmdline;
|
||||
for (auto &Arg : Cmd.CommandLine)
|
||||
for (auto &Arg : Cmd->CommandLine)
|
||||
Cmdline += Arg + " ";
|
||||
elog("The command line the scanning tool use is: {0}", Cmdline);
|
||||
return std::nullopt;
|
||||
@@ -227,6 +238,13 @@ public:
|
||||
return *ScanningResult->ModuleName;
|
||||
}
|
||||
|
||||
// Determining Unique/Multiple needs a global scan; return Unknown for cost
|
||||
// reasons. We will have other ProjectModules implementations can determine
|
||||
// this more efficiently.
|
||||
ModuleNameState getModuleNameState(llvm::StringRef /*ModuleName*/) override {
|
||||
return ModuleNameState::Unknown;
|
||||
}
|
||||
|
||||
private:
|
||||
ModuleDependencyScanner Scanner;
|
||||
CommandMangler Mangler;
|
||||
|
||||
@@ -38,6 +38,12 @@ namespace clangd {
|
||||
/// `<primary-module-name>[:partition-name]`. So module names covers partitions.
|
||||
class ProjectModules {
|
||||
public:
|
||||
enum class ModuleNameState {
|
||||
Unknown,
|
||||
Unique,
|
||||
Multiple,
|
||||
};
|
||||
|
||||
using CommandMangler =
|
||||
llvm::unique_function<void(tooling::CompileCommand &, PathRef) const>;
|
||||
|
||||
@@ -45,6 +51,9 @@ public:
|
||||
virtual std::string getModuleNameForSource(PathRef File) = 0;
|
||||
virtual std::string getSourceForModuleName(llvm::StringRef ModuleName,
|
||||
PathRef RequiredSrcFile) = 0;
|
||||
virtual ModuleNameState getModuleNameState(llvm::StringRef ModuleName) {
|
||||
return ModuleNameState::Unknown;
|
||||
}
|
||||
|
||||
virtual void setCommandMangler(CommandMangler Mangler) {}
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ public:
|
||||
return Underlying->getSourceForModuleName(ModuleName, RequiredSrcFile);
|
||||
}
|
||||
|
||||
ModuleNameState getModuleNameState(llvm::StringRef ModuleName) override {
|
||||
return Underlying->getModuleNameState(ModuleName);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<ProjectModules> Underlying;
|
||||
std::atomic<unsigned> &Count;
|
||||
|
||||
Reference in New Issue
Block a user