Skip to content

Commit 30beba1

Browse files
[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
1 parent be92320 commit 30beba1

File tree

7 files changed

+155
-3
lines changed

7 files changed

+155
-3
lines changed

Diff for: include/swift/Option/Options.td

+20
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,16 @@ def symbol_graph_minimum_access_level: Separate<["-"], "symbol-graph-minimum-acc
17741774
HelpText<"Include symbols with this access level or more when emitting a symbol graph">,
17751775
MetaVarName<"<level>">;
17761776

1777+
def symbol_graph_allow_availability_platforms: Separate<["-"], "symbol-graph-allow-availability-platforms">,
1778+
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, HelpHidden]>,
1779+
HelpText<"Restrict availability metadata to the given platforms, e.g. 'macOS,Swift'">,
1780+
MetaVarName<"<platforms>">;
1781+
1782+
def symbol_graph_block_availability_platforms: Separate<["-"], "symbol-graph-block-availability-platforms">,
1783+
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, HelpHidden]>,
1784+
HelpText<"Remove the given platforms from symbol graph availability metadata, e.g. 'macOS,Swift'">,
1785+
MetaVarName<"<platforms>">;
1786+
17771787
def pretty_print: Flag<["-"], "pretty-print">,
17781788
Flags<[SwiftSymbolGraphExtractOption]>,
17791789
HelpText<"Pretty-print the output JSON">;
@@ -1788,6 +1798,16 @@ def omit_extension_block_symbols: Flag<["-"], "omit-extension-block-symbols">,
17881798
NoInteractiveOption, SupplementaryOutput, HelpHidden]>,
17891799
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">;
17901800

1801+
def allow_availability_platforms: Separate<["-"], "allow-availability-platforms">,
1802+
Flags<[SwiftSymbolGraphExtractOption]>,
1803+
HelpText<"Restrict availability metadata to the given platforms, e.g. 'macOS,Swift'">,
1804+
MetaVarName<"<platforms>">;
1805+
1806+
def block_availability_platforms: Separate<["-"], "block-availability-platforms">,
1807+
Flags<[SwiftSymbolGraphExtractOption]>,
1808+
HelpText<"Remove the given platforms from symbol graph availability metadata, e.g. 'macOS,Swift'">,
1809+
MetaVarName<"<platforms>">;
1810+
17911811
// swift-synthesize-interface-only options
17921812
def include_submodules : Flag<["-"], "include-submodules">,
17931813
Flags<[NoDriverOption, SwiftSynthesizeInterfaceOption]>,

Diff for: include/swift/SymbolGraphGen/SymbolGraphOptions.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "llvm/TargetParser/Triple.h"
1413
#include "llvm/ADT/ArrayRef.h"
14+
#include "llvm/ADT/DenseSet.h"
15+
#include "llvm/TargetParser/Triple.h"
1516

1617
#include "swift/AST/AttrKind.h"
1718

@@ -69,6 +70,13 @@ struct SymbolGraphOptions {
6970
/// If this has a value specifies an explicit allow list of reexported module
7071
/// names that should be included symbol graph.
7172
std::optional<llvm::ArrayRef<StringRef>> AllowedReexportedModules = {};
73+
74+
/// If set, a list of availability platforms to restrict (or block) when
75+
/// rendering symbol graphs.
76+
std::optional<llvm::DenseSet<StringRef>> AvailabilityPlatforms = {};
77+
78+
/// Whether `AvailabilityPlatforms` is an allow list or a block list.
79+
bool AvailabilityIsBlockList = false;
7280
};
7381

7482
} // end namespace symbolgraphgen

Diff for: lib/DriverTool/swift_symbolgraph_extract_main.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,25 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
203203
.Default(AccessLevel::Public);
204204
}
205205

206+
if (auto *A = ParsedArgs.getLastArg(OPT_allow_availability_platforms)) {
207+
llvm::SmallVector<StringRef> AvailabilityPlatforms;
208+
StringRef(A->getValue())
209+
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
210+
/*KeepEmpty*/ false);
211+
Options.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
212+
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
213+
Options.AvailabilityIsBlockList = false;
214+
} else if (auto *A =
215+
ParsedArgs.getLastArg(OPT_block_availability_platforms)) {
216+
llvm::SmallVector<StringRef> AvailabilityPlatforms;
217+
StringRef(A->getValue())
218+
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
219+
/*KeepEmpty*/ false);
220+
Options.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
221+
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
222+
Options.AvailabilityIsBlockList = true;
223+
}
224+
206225
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags);
207226

208227
std::string InstanceSetupError;

Diff for: lib/Frontend/CompilerInvocation.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -2221,6 +2221,25 @@ static void ParseSymbolGraphArgs(symbolgraphgen::SymbolGraphOptions &Opts,
22212221
Opts.MinimumAccessLevel = AccessLevel::Public;
22222222
}
22232223

2224+
if (auto *A = Args.getLastArg(OPT_symbol_graph_allow_availability_platforms)) {
2225+
llvm::SmallVector<StringRef> AvailabilityPlatforms;
2226+
StringRef(A->getValue())
2227+
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
2228+
/*KeepEmpty*/ false);
2229+
Opts.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
2230+
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
2231+
Opts.AvailabilityIsBlockList = false;
2232+
} else if (auto *A = Args.getLastArg(
2233+
OPT_symbol_graph_block_availability_platforms)) {
2234+
llvm::SmallVector<StringRef> AvailabilityPlatforms;
2235+
StringRef(A->getValue())
2236+
.split(AvailabilityPlatforms, ',', /*MaxSplits*/ -1,
2237+
/*KeepEmpty*/ false);
2238+
Opts.AvailabilityPlatforms = llvm::DenseSet<StringRef>(
2239+
AvailabilityPlatforms.begin(), AvailabilityPlatforms.end());
2240+
Opts.AvailabilityIsBlockList = true;
2241+
}
2242+
22242243
// default values for generating symbol graphs during a build
22252244
Opts.PrettyPrint = false;
22262245
Opts.EmitSynthesizedMembers = true;

Diff for: lib/SymbolGraphGen/Symbol.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,26 @@ void Symbol::serializeAvailabilityMixin(llvm::json::OStream &OS) const {
697697
llvm::StringMap<Availability> Availabilities;
698698
getInheritedAvailabilities(D, Availabilities);
699699

700+
// If we were asked to filter the availability platforms for the output graph,
701+
// perform that filtering here.
702+
if (Graph->Walker.Options.AvailabilityPlatforms) {
703+
auto AvailabilityPlatforms =
704+
Graph->Walker.Options.AvailabilityPlatforms.value();
705+
if (Graph->Walker.Options.AvailabilityIsBlockList) {
706+
for (const auto Availability : Availabilities.keys()) {
707+
if (Availability != "*" && AvailabilityPlatforms.contains(Availability)) {
708+
Availabilities.erase(Availability);
709+
}
710+
}
711+
} else {
712+
for (const auto Availability : Availabilities.keys()) {
713+
if (Availability != "*" && !AvailabilityPlatforms.contains(Availability)) {
714+
Availabilities.erase(Availability);
715+
}
716+
}
717+
}
718+
}
719+
700720
if (Availabilities.empty()) {
701721
return;
702722
}

Diff for: stdlib/cmake/modules/AddSwiftStdlib.cmake

+5-2
Original file line numberDiff line numberDiff line change
@@ -926,11 +926,14 @@ function(add_swift_target_library_single target name)
926926
endif()
927927
endif()
928928

929-
# FIXME: swiftDarwin currently trips an assertion in SymbolGraphGen
930-
if (SWIFTLIB_IS_STDLIB AND SWIFT_STDLIB_BUILD_SYMBOL_GRAPHS AND NOT ${name} STREQUAL "swiftDarwin")
929+
# FIXME: swiftDarwin and swiftDifferentiationUnittest currently trip an assertion in SymbolGraphGen
930+
if (SWIFTLIB_IS_STDLIB AND SWIFT_STDLIB_BUILD_SYMBOL_GRAPHS AND NOT ${name} STREQUAL "swiftDarwin"
931+
AND NOT ${name} STREQUAL "swiftDifferentiationUnittest")
931932
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS "-Xfrontend;-emit-symbol-graph")
932933
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS
933934
"-Xfrontend;-emit-symbol-graph-dir;-Xfrontend;${out_lib_dir}/symbol-graph/${VARIANT_NAME}")
935+
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS
936+
"-Xfrontend;-symbol-graph-allow-availability-platforms;-Xfrontend;Swift")
934937
endif()
935938

936939
if(MODULE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -module-name AvailabilityFilter -emit-module -emit-module-path %t/AvailabilityFilter.swiftmodule -emit-symbol-graph -emit-symbol-graph-dir %t/
3+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix DEFAULT
4+
5+
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t
6+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix DEFAULT
7+
8+
// Now checking the allowlist behavior...
9+
10+
// RUN: %empty-directory(%t)
11+
// 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
12+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix ALLOWLIST
13+
14+
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t -allow-availability-platforms macOS,iOS
15+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix ALLOWLIST
16+
17+
// Now checking the blocklist behavior...
18+
19+
// RUN: %empty-directory(%t)
20+
// 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
21+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix BLOCKLIST
22+
23+
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t -block-availability-platforms macOS,iOS
24+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix BLOCKLIST
25+
26+
// Now test to ensure an empty allow list filters out all availability...
27+
28+
// RUN: %empty-directory(%t)
29+
// 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 ""
30+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix EMPTY
31+
32+
// RUN: %target-swift-symbolgraph-extract -module-name AvailabilityFilter -I %t -pretty-print -output-dir %t -allow-availability-platforms ""
33+
// RUN: %FileCheck %s --input-file %t/AvailabilityFilter.symbols.json --check-prefix EMPTY
34+
35+
// REQUIRES: OS=macosx
36+
37+
@available(macOS 11.0, iOS 15.0, watchOS 15.0, *)
38+
public struct S {}
39+
40+
/// Ensure that regardless of platforms being removed, that universal availability info,
41+
/// like unconditional deprecation, still lands in the symbol graph.
42+
@available(*, deprecated)
43+
public class C {}
44+
45+
// DEFAULT-DAG: macOS
46+
// DEFAULT-DAG: iOS
47+
// DEFAULT-DAG: watchOS
48+
// DEFAULT-DAG: "isUnconditionallyDeprecated":{{ ?}}true
49+
50+
// ALLOWLIST-NOT: watchOS
51+
// ALLOWLIST-DAG: macOS
52+
// ALLOWLIST-DAG: iOS
53+
// ALLOWLIST-DAG: "isUnconditionallyDeprecated":{{ ?}}true
54+
55+
// BLOCKLIST-NOT: macOS
56+
// BLOCKLIST-NOT: iOS
57+
// BLOCKLIST-DAG: watchOS
58+
// BLOCKLIST-DAG: "isUnconditionallyDeprecated":{{ ?}}true
59+
60+
// EMPTY-NOT: macOS
61+
// EMPTY-NOT: iOS
62+
// EMPTY-NOT: watchOS
63+
// EMPTY-DAG: "isUnconditionallyDeprecated":{{ ?}}true

0 commit comments

Comments
 (0)