[clang][ExtractAPI] Add multiple file support to --extract-api-ignores

- Modify -extract-api-ignores command line option to accept multiple
  arguments
- Update APIIgnoresList to operate on a file list instead of a single file
- Add new test verifying the functionality
- fix #61242 on GitHub issue tracker

Reviewed By: dang

Differential Revision: https://reviews.llvm.org/D145869
This commit is contained in:
Ankur 2023-03-13 17:58:39 +05:30
parent 5a0ad86cf3
commit 58825d2cf9
6 changed files with 83 additions and 27 deletions

View File

@ -1167,9 +1167,9 @@ def extract_api : Flag<["-"], "extract-api">, Flags<[CC1Option]>, Group<Action_G
HelpText<"Extract API information">;
def product_name_EQ: Joined<["--"], "product-name=">, Flags<[CC1Option]>,
MarshallingInfoString<FrontendOpts<"ProductName">>;
def extract_api_ignores_EQ: Joined<["--"], "extract-api-ignores=">, Flags<[CC1Option]>,
HelpText<"File containing a new line separated list of API symbols to ignore when extracting API information.">,
MarshallingInfoString<FrontendOpts<"ExtractAPIIgnoresFile">>;
def extract_api_ignores_EQ: CommaJoined<["--"], "extract-api-ignores=">, Flags<[CC1Option]>,
HelpText<"Comma separated list of files containing a new line separated list of API symbols to ignore when extracting API information.">,
MarshallingInfoStringVector<FrontendOpts<"ExtractAPIIgnoresFileList">>;
def e : JoinedOrSeparate<["-"], "e">, Flags<[LinkerInput]>, Group<Link_Group>;
def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Max total number of preprocessed tokens for -Wmax-tokens.">,

View File

@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
///
/// \file This file defines APIIgnoresList which is a type that allows querying
/// a file containing symbols to ignore when extracting API information.
/// files containing symbols to ignore when extracting API information.
///
//===----------------------------------------------------------------------===//
@ -44,11 +44,13 @@ struct IgnoresFileNotFound : public llvm::ErrorInfo<IgnoresFileNotFound> {
/// A type that provides access to a new line separated list of symbol names to
/// ignore when extracting API information.
struct APIIgnoresList {
/// The API to use for generating from the file at \p IgnoresFilePath.
using FilePathList = std::vector<std::string>;
/// The API to use for generating from the files at \p IgnoresFilePathList.
///
/// \returns an initialized APIIgnoresList or an Error.
static llvm::Expected<APIIgnoresList> create(llvm::StringRef IgnoresFilePath,
FileManager &FM);
static llvm::Expected<APIIgnoresList>
create(const FilePathList &IgnoresFilePathList, FileManager &FM);
APIIgnoresList() = default;
@ -58,14 +60,14 @@ struct APIIgnoresList {
private:
using SymbolNameList = llvm::SmallVector<llvm::StringRef, 32>;
using BufferList = llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>>;
APIIgnoresList(SymbolNameList SymbolsToIgnore,
std::unique_ptr<llvm::MemoryBuffer> Buffer)
: SymbolsToIgnore(std::move(SymbolsToIgnore)), Buffer(std::move(Buffer)) {
}
APIIgnoresList(SymbolNameList SymbolsToIgnore, BufferList Buffers)
: SymbolsToIgnore(std::move(SymbolsToIgnore)),
Buffers(std::move(Buffers)) {}
SymbolNameList SymbolsToIgnore;
std::unique_ptr<llvm::MemoryBuffer> Buffer;
BufferList Buffers;
};
} // namespace extractapi

View File

@ -453,8 +453,9 @@ public:
std::string ProductName;
// Currently this is only used as part of the `-extract-api` action.
/// The file providing a list of APIs to ignore when extracting documentation
std::string ExtractAPIIgnoresFile;
// A comma seperated list of files providing a list of APIs to
// ignore when extracting documentation.
std::vector<std::string> ExtractAPIIgnoresFileList;
/// Args to pass to the plugins
std::map<std::string, std::vector<std::string>> PluginArgs;

View File

@ -31,20 +31,29 @@ std::error_code IgnoresFileNotFound::convertToErrorCode() const {
return llvm::inconvertibleErrorCode();
}
Expected<APIIgnoresList> APIIgnoresList::create(StringRef IgnoresFilePath,
FileManager &FM) {
auto BufferOrErr = FM.getBufferForFile(IgnoresFilePath);
if (!BufferOrErr)
return make_error<IgnoresFileNotFound>(IgnoresFilePath);
auto Buffer = std::move(BufferOrErr.get());
Expected<APIIgnoresList>
APIIgnoresList::create(const FilePathList &IgnoresFilePathList,
FileManager &FM) {
SmallVector<StringRef, 32> Lines;
Buffer->getBuffer().split(Lines, '\n', /*MaxSplit*/ -1, /*KeepEmpty*/ false);
// Symbol names don't have spaces in them, let's just remove these in case the
// input is slighlty malformed.
BufferList symbolBufferList;
for (const auto &CurrentIgnoresFilePath : IgnoresFilePathList) {
auto BufferOrErr = FM.getBufferForFile(CurrentIgnoresFilePath);
if (!BufferOrErr)
return make_error<IgnoresFileNotFound>(CurrentIgnoresFilePath);
auto Buffer = std::move(BufferOrErr.get());
Buffer->getBuffer().split(Lines, '\n', /*MaxSplit*/ -1,
/*KeepEmpty*/ false);
symbolBufferList.push_back(std::move(Buffer));
}
// Symbol names don't have spaces in them, let's just remove these in case
// the input is slighlty malformed.
transform(Lines, Lines.begin(), [](StringRef Line) { return Line.trim(); });
sort(Lines);
return APIIgnoresList(std::move(Lines), std::move(Buffer));
return APIIgnoresList(std::move(Lines), std::move(symbolBufferList));
}
bool APIIgnoresList::shouldIgnore(StringRef SymbolName) const {

View File

@ -339,9 +339,9 @@ ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
Policy.AnonymousTagLocations = false;
CI.getASTContext().setPrintingPolicy(Policy);
if (!CI.getFrontendOpts().ExtractAPIIgnoresFile.empty()) {
if (!CI.getFrontendOpts().ExtractAPIIgnoresFileList.empty()) {
llvm::handleAllErrors(
APIIgnoresList::create(CI.getFrontendOpts().ExtractAPIIgnoresFile,
APIIgnoresList::create(CI.getFrontendOpts().ExtractAPIIgnoresFileList,
CI.getFileManager())
.moveInto(IgnoresList),
[&CI](const IgnoresFileNotFound &Err) {

View File

@ -0,0 +1,44 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: --extract-api-ignores=%t/ignores-list1,%t/ignores-list2,%t/ignores-list3 \
// RUN: -x c-header %t/input.h -verify -o - | FileCheck %t/input.h
//--- input.h
#define IGNORED_6_FILE1 6
#define IGNORED_2_FILE1 2
#define IGNORED_5_FILE1 5
#define IGNORED_4_FILE2 4
#define IGNORED_3_FILE2 3
typedef double IGNORED_1_FILE3;
typedef int IGNORED_7_FILE3;
typedef float NonIgnored;
// CHECK-NOT: IGNORED_6_FILE1
// CHECK-NOT: IGNORED_2_FILE1
// CHECK-NOT: IGNORED_5_FILE1
// CHECK-NOT: IGNORED_4_FILE2
// CHECK-NOT: IGNORED_3_FILE2
// CHECK-NOT: IGNORED_1_FILE3
// CHECK-NOT: IGNORED_7_FILE3
// CHECK: NonIgnored
// expected-no-diagnostics
//--- ignores-list1
IGNORED_6_FILE1
IGNORED_2_FILE1
IGNORED_5_FILE1
//--- ignores-list2
IGNORED_4_FILE2
IGNORED_3_FILE2
//--- ignores-list3
IGNORED_1_FILE3
IGNORED_7_FILE3