mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[SymbolGraphGen] add flags to filter platforms out of availability metadata (#80778)
* add option to filter availability metadata in symbol graphs * filter out platform-specific availability in the stdlib docs rdar://144379124
This commit is contained in:
@@ -1764,6 +1764,16 @@ def symbol_graph_minimum_access_level: Separate<["-"], "symbol-graph-minimum-acc
|
||||
HelpText<"Include symbols with this access level or more when emitting a symbol graph">,
|
||||
MetaVarName<"<level>">;
|
||||
|
||||
def symbol_graph_allow_availability_platforms: Separate<["-"], "symbol-graph-allow-availability-platforms">,
|
||||
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, HelpHidden]>,
|
||||
HelpText<"Restrict availability metadata to the given platforms, e.g. 'macOS,Swift'">,
|
||||
MetaVarName<"<platforms>">;
|
||||
|
||||
def symbol_graph_block_availability_platforms: Separate<["-"], "symbol-graph-block-availability-platforms">,
|
||||
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, HelpHidden]>,
|
||||
HelpText<"Remove the given platforms from symbol graph availability metadata, e.g. 'macOS,Swift'">,
|
||||
MetaVarName<"<platforms>">;
|
||||
|
||||
def pretty_print: Flag<["-"], "pretty-print">,
|
||||
Flags<[SwiftSymbolGraphExtractOption]>,
|
||||
HelpText<"Pretty-print the output JSON">;
|
||||
@@ -1778,6 +1788,16 @@ def omit_extension_block_symbols: Flag<["-"], "omit-extension-block-symbols">,
|
||||
NoInteractiveOption, SupplementaryOutput, HelpHidden]>,
|
||||
HelpText<"Directly associate members and conformances with the extended nominal when generating symbol graphs instead of emitting 'swift.extension' symbols for extensions to external types">;
|
||||
|
||||
def allow_availability_platforms: Separate<["-"], "allow-availability-platforms">,
|
||||
Flags<[SwiftSymbolGraphExtractOption]>,
|
||||
HelpText<"Restrict availability metadata to the given platforms, e.g. 'macOS,Swift'">,
|
||||
MetaVarName<"<platforms>">;
|
||||
|
||||
def block_availability_platforms: Separate<["-"], "block-availability-platforms">,
|
||||
Flags<[SwiftSymbolGraphExtractOption]>,
|
||||
HelpText<"Remove the given platforms from symbol graph availability metadata, e.g. 'macOS,Swift'">,
|
||||
MetaVarName<"<platforms>">;
|
||||
|
||||
// swift-synthesize-interface-only options
|
||||
def include_submodules : Flag<["-"], "include-submodules">,
|
||||
Flags<[NoDriverOption, SwiftSynthesizeInterfaceOption]>,
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
|
||||
#include "swift/AST/AttrKind.h"
|
||||
|
||||
@@ -69,6 +70,13 @@ struct SymbolGraphOptions {
|
||||
/// If this has a value specifies an explicit allow list of reexported module
|
||||
/// names that should be included symbol graph.
|
||||
std::optional<llvm::ArrayRef<StringRef>> AllowedReexportedModules = {};
|
||||
|
||||
/// If set, a list of availability platforms to restrict (or block) when
|
||||
/// rendering symbol graphs.
|
||||
std::optional<llvm::DenseSet<StringRef>> AvailabilityPlatforms = {};
|
||||
|
||||
/// Whether `AvailabilityPlatforms` is an allow list or a block list.
|
||||
bool AvailabilityIsBlockList = false;
|
||||
};
|
||||
|
||||
} // end namespace symbolgraphgen
|
||||
|
||||
@@ -203,6 +203,25 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
|
||||
.Default(AccessLevel::Public);
|
||||
}
|
||||
|
||||
if (auto *A = ParsedArgs.getLastArg(OPT_allow_availability_platforms)) {
|
||||
llvm::SmallVector<StringRef> AvailabilityPlatforms;
|
||||
StringRef(A->getValue())
|
||||
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
|
||||
/*KeepEmpty*/ false);
|
||||
Options.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
|
||||
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
|
||||
Options.AvailabilityIsBlockList = false;
|
||||
} else if (auto *A =
|
||||
ParsedArgs.getLastArg(OPT_block_availability_platforms)) {
|
||||
llvm::SmallVector<StringRef> AvailabilityPlatforms;
|
||||
StringRef(A->getValue())
|
||||
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
|
||||
/*KeepEmpty*/ false);
|
||||
Options.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
|
||||
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
|
||||
Options.AvailabilityIsBlockList = true;
|
||||
}
|
||||
|
||||
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags);
|
||||
|
||||
std::string InstanceSetupError;
|
||||
|
||||
@@ -2215,6 +2215,25 @@ static void ParseSymbolGraphArgs(symbolgraphgen::SymbolGraphOptions &Opts,
|
||||
Opts.MinimumAccessLevel = AccessLevel::Public;
|
||||
}
|
||||
|
||||
if (auto *A = Args.getLastArg(OPT_symbol_graph_allow_availability_platforms)) {
|
||||
llvm::SmallVector<StringRef> AvailabilityPlatforms;
|
||||
StringRef(A->getValue())
|
||||
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
|
||||
/*KeepEmpty*/ false);
|
||||
Opts.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
|
||||
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
|
||||
Opts.AvailabilityIsBlockList = false;
|
||||
} else if (auto *A = Args.getLastArg(
|
||||
OPT_symbol_graph_block_availability_platforms)) {
|
||||
llvm::SmallVector<StringRef> AvailabilityPlatforms;
|
||||
StringRef(A->getValue())
|
||||
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
|
||||
/*KeepEmpty*/ false);
|
||||
Opts.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
|
||||
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
|
||||
Opts.AvailabilityIsBlockList = true;
|
||||
}
|
||||
|
||||
// default values for generating symbol graphs during a build
|
||||
Opts.PrettyPrint = false;
|
||||
Opts.EmitSynthesizedMembers = true;
|
||||
|
||||
@@ -697,6 +697,26 @@ void Symbol::serializeAvailabilityMixin(llvm::json::OStream &OS) const {
|
||||
llvm::StringMap<Availability> Availabilities;
|
||||
getInheritedAvailabilities(D, Availabilities);
|
||||
|
||||
// If we were asked to filter the availability platforms for the output graph,
|
||||
// perform that filtering here.
|
||||
if (Graph->Walker.Options.AvailabilityPlatforms) {
|
||||
auto AvailabilityPlatforms =
|
||||
Graph->Walker.Options.AvailabilityPlatforms.value();
|
||||
if (Graph->Walker.Options.AvailabilityIsBlockList) {
|
||||
for (const auto Availability : Availabilities.keys()) {
|
||||
if (Availability != "*" && AvailabilityPlatforms.contains(Availability)) {
|
||||
Availabilities.erase(Availability);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto Availability : Availabilities.keys()) {
|
||||
if (Availability != "*" && !AvailabilityPlatforms.contains(Availability)) {
|
||||
Availabilities.erase(Availability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Availabilities.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -932,11 +932,14 @@ function(add_swift_target_library_single target name)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FIXME: swiftDarwin currently trips an assertion in SymbolGraphGen
|
||||
if (SWIFTLIB_IS_STDLIB AND SWIFT_STDLIB_BUILD_SYMBOL_GRAPHS AND NOT ${name} STREQUAL "swiftDarwin")
|
||||
# FIXME: swiftDarwin and swiftDifferentiationUnittest currently trip an assertion in SymbolGraphGen
|
||||
if (SWIFTLIB_IS_STDLIB AND SWIFT_STDLIB_BUILD_SYMBOL_GRAPHS AND NOT ${name} STREQUAL "swiftDarwin"
|
||||
AND NOT ${name} STREQUAL "swiftDifferentiationUnittest")
|
||||
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS "-Xfrontend;-emit-symbol-graph")
|
||||
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS
|
||||
"-Xfrontend;-emit-symbol-graph-dir;-Xfrontend;${out_lib_dir}/symbol-graph/${VARIANT_NAME}")
|
||||
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS
|
||||
"-Xfrontend;-symbol-graph-allow-availability-platforms;-Xfrontend;Swift")
|
||||
endif()
|
||||
|
||||
if(MODULE)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -module-name AvailabilityFilter -emit-module -emit-module-path %t/AvailabilityFilter.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix DEFAULT
|
||||
|
||||
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix DEFAULT
|
||||
|
||||
// Now checking the allowlist behavior...
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -module-name AvailabilityFilter -emit-module -emit-module-path %t/AvailabilityFilter.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/ -symbol-graph-allow-availability-platforms macOS,iOS
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix ALLOWLIST
|
||||
|
||||
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t -allow-availability-platforms macOS,iOS
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix ALLOWLIST
|
||||
|
||||
// Now checking the blocklist behavior...
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -module-name AvailabilityFilter -emit-module -emit-module-path %t/AvailabilityFilter.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/ -symbol-graph-block-availability-platforms macOS,iOS
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix BLOCKLIST
|
||||
|
||||
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t -block-availability-platforms macOS,iOS
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix BLOCKLIST
|
||||
|
||||
// Now test to ensure an empty allow list filters out all availability...
|
||||
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend %s -module-name AvailabilityFilter -emit-module -emit-module-path %t/AvailabilityFilter.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/ -symbol-graph-allow-availability-platforms ""
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix EMPTY
|
||||
|
||||
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t -allow-availability-platforms ""
|
||||
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix EMPTY
|
||||
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
@available(macOS 11.0, iOS 15.0, watchOS 15.0, *)
|
||||
public struct S {}
|
||||
|
||||
/// Ensure that regardless of platforms being removed, that universal availability info,
|
||||
/// like unconditional deprecation, still lands in the symbol graph.
|
||||
@available(*, deprecated)
|
||||
public class C {}
|
||||
|
||||
// DEFAULT-DAG: macOS
|
||||
// DEFAULT-DAG: iOS
|
||||
// DEFAULT-DAG: watchOS
|
||||
// DEFAULT-DAG: "isUnconditionallyDeprecated":{{ ?}}true
|
||||
|
||||
// ALLOWLIST-NOT: watchOS
|
||||
// ALLOWLIST-DAG: macOS
|
||||
// ALLOWLIST-DAG: iOS
|
||||
// ALLOWLIST-DAG: "isUnconditionallyDeprecated":{{ ?}}true
|
||||
|
||||
// BLOCKLIST-NOT: macOS
|
||||
// BLOCKLIST-NOT: iOS
|
||||
// BLOCKLIST-DAG: watchOS
|
||||
// BLOCKLIST-DAG: "isUnconditionallyDeprecated":{{ ?}}true
|
||||
|
||||
// EMPTY-NOT: macOS
|
||||
// EMPTY-NOT: iOS
|
||||
// EMPTY-NOT: watchOS
|
||||
// EMPTY-DAG: "isUnconditionallyDeprecated":{{ ?}}true
|
||||
Reference in New Issue
Block a user