diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index b2e04578de7f8..22f7a49ccb347 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -23,18 +23,12 @@ #include "swift/AST/Identifier.h" #include "swift/AST/Import.h" #include "swift/AST/ProtocolConformanceOptions.h" -#include "swift/AST/SILOptions.h" -#include "swift/AST/SearchPathOptions.h" #include "swift/AST/Type.h" #include "swift/AST/TypeAlignments.h" #include "swift/AST/Types.h" #include "swift/Basic/BlockList.h" -#include "swift/Basic/CASOptions.h" -#include "swift/Basic/LangOptions.h" #include "swift/Basic/Located.h" #include "swift/Basic/Malloc.h" -#include "swift/Serialization/SerializationOptions.h" -#include "swift/SymbolGraphGen/SymbolGraphOptions.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/DarwinSDKInfo.h" #include "llvm/ADT/ArrayRef.h" @@ -77,6 +71,7 @@ namespace swift { class AvailabilityRange; class BoundGenericType; class BuiltinTupleDecl; + class CASOptions; class ClangModuleLoader; class ClangNode; class ClangTypeConverter; @@ -100,6 +95,7 @@ namespace swift { class LazyContextData; class LazyIterableDeclContextData; class LazyMemberLoader; + class LangOptions; struct MacroDiscriminatorContext; class ModuleInterfaceChecker; class PatternBindingDecl; @@ -107,13 +103,14 @@ namespace swift { class PluginLoader; class SourceFile; class SourceLoc; + class SerializationOptions; + class SILOptions; struct TemplateInstantiationError; class Type; class TypeVariableType; class TupleType; class FunctionType; class ArchetypeType; - class Identifier; class InheritedNameSet; class ModuleDecl; class PackageUnit; @@ -142,6 +139,7 @@ namespace swift { class DiagnosticEngine; struct RawComment; class DocComment; + class SearchPathOptions; class SILBoxType; class SILTransform; class TypeAliasDecl; @@ -165,6 +163,10 @@ namespace ide { class TypeCheckCompletionCallback; } +namespace symbolgraphgen { + struct SymbolGraphOptions; +} + /// Lists the set of "known" Foundation entities that are used in the /// compiler. /// diff --git a/include/swift/AST/PlatformKindUtils.h b/include/swift/AST/PlatformKindUtils.h index e0f3f240a0e9e..763e342c3988a 100644 --- a/include/swift/AST/PlatformKindUtils.h +++ b/include/swift/AST/PlatformKindUtils.h @@ -80,6 +80,10 @@ PlatformKind targetPlatform(const LangOptions &LangOpts); /// Returns the target variant platform for the given language options. PlatformKind targetVariantPlatform(const LangOptions &LangOpts); +/// Returns the target platform for the given triple and options. +PlatformKind platformForTriple(const llvm::Triple &triple, + bool enableAppExtensionRestrictions); + /// Returns true when availability attributes from the "parent" platform /// should also apply to the "child" platform for declarations without /// an explicit attribute for the child. diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index b9f1217230dc2..e330d2ff87fab 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1939,6 +1939,12 @@ def block_availability_platforms: Separate<["-"], "block-availability-platforms" HelpText<"Remove the given platforms from symbol graph availability metadata, e.g. 'macOS,Swift'">, MetaVarName<"">; +def active_platform_availability_only + : Flag<["-"], "active-platform-availability-only">, + Flags<[SwiftSymbolGraphExtractOption]>, + HelpText<"Only emit availability metadata for platforms that are active " + "according to the target">; + // swift-synthesize-interface-only options def include_submodules : Flag<["-"], "include-submodules">, Flags<[NoDriverOption, SwiftSynthesizeInterfaceOption]>, diff --git a/include/swift/SymbolGraphGen/SymbolGraphOptions.h b/include/swift/SymbolGraphGen/SymbolGraphOptions.h index 3b43314dc9dba..82d859cb7f2b2 100644 --- a/include/swift/SymbolGraphGen/SymbolGraphOptions.h +++ b/include/swift/SymbolGraphGen/SymbolGraphOptions.h @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "swift/AST/PlatformKind.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/TargetParser/Triple.h" @@ -78,6 +79,9 @@ struct SymbolGraphOptions { /// Whether `AvailabilityPlatforms` is an allow list or a block list. bool AvailabilityIsBlockList = false; + /// If non-null, only emit availability metadata for the active platform. + std::optional ActivePlatform = std::nullopt; + /// Whether to use shortened, by using a hash of the module names, file names /// when writing symbol graph files to `OutputDir`. /// An additional JSON file is written at `OutputDir` that contains a mapping diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index adf39d5aec6b0..768e9c6e99fd0 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -40,6 +40,7 @@ #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PrintOptions.h" #include "swift/AST/ProtocolConformance.h" +#include "swift/AST/SearchPathOptions.h" #include "swift/AST/SourceFile.h" #include "swift/AST/SourceFileExtras.h" #include "swift/AST/SynthesizedFileUnit.h" diff --git a/lib/AST/PlatformKindUtils.cpp b/lib/AST/PlatformKindUtils.cpp index 1b56a5968f1e3..f4a3454ed3b9e 100644 --- a/lib/AST/PlatformKindUtils.cpp +++ b/lib/AST/PlatformKindUtils.cpp @@ -194,7 +194,7 @@ bool swift::isPlatformActive(PlatformKind Platform, const LangOptions &LangOpts, ForRuntimeQuery); } -static PlatformKind platformForTriple(const llvm::Triple &triple, +PlatformKind swift::platformForTriple(const llvm::Triple &triple, bool enableAppExtensionRestrictions) { if (triple.isMacOSX()) { return (enableAppExtensionRestrictions diff --git a/lib/AST/PluginLoader.cpp b/lib/AST/PluginLoader.cpp index 571ab68df061a..46617ad685fa1 100644 --- a/lib/AST/PluginLoader.cpp +++ b/lib/AST/PluginLoader.cpp @@ -14,7 +14,9 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsSema.h" +#include "swift/AST/SearchPathOptions.h" #include "swift/Basic/Assertions.h" +#include "swift/Basic/CASOptions.h" #include "swift/Basic/SourceManager.h" #include "swift/Parse/Lexer.h" #include "llvm/Config/config.h" diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 832fb388b3d46..5bc725811f7c6 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -14,6 +14,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsClangImporter.h" +#include "swift/AST/SearchPathOptions.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/Platform.h" #include "swift/ClangImporter/ClangImporter.h" diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index e4258b31bed3c..b0a3ebd1a0af0 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -16,9 +16,10 @@ #include "ImporterImpl.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/ModuleDependencies.h" +#include "swift/Basic/Assertions.h" +#include "swift/Basic/CASOptions.h" #include "swift/Basic/SourceManager.h" #include "swift/ClangImporter/ClangImporter.h" -#include "swift/Basic/Assertions.h" #include "clang/Basic/Diagnostic.h" #include "clang/CAS/CASOptions.h" #include "clang/Frontend/CompilerInvocation.h" @@ -28,8 +29,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Signals.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/StringSaver.h" using namespace swift; diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 82411b3b0cdc7..316d971314866 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -42,6 +42,7 @@ #include "swift/AST/Pattern.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" +#include "swift/AST/SILOptions.h" #include "swift/AST/Stmt.h" #include "swift/AST/Type.h" #include "swift/AST/TypeCheckRequests.h" diff --git a/lib/DriverTool/swift_symbolgraph_extract_main.cpp b/lib/DriverTool/swift_symbolgraph_extract_main.cpp index 764458c18fcac..245987b59e1a2 100644 --- a/lib/DriverTool/swift_symbolgraph_extract_main.cpp +++ b/lib/DriverTool/swift_symbolgraph_extract_main.cpp @@ -190,6 +190,13 @@ int swift_symbolgraph_extract_main(ArrayRef Args, ParsedArgs.hasFlag(OPT_emit_extension_block_symbols, OPT_omit_extension_block_symbols, /*default=*/false); Options.AllowedReexportedModules = AllowedRexports; + if (ParsedArgs.hasArg(OPT_active_platform_availability_only)) { + // The output should only include platform availability that applies to the + // platform inferred from the -target. Include app extension availability, + // too. + Options.ActivePlatform = + platformForTriple(Target, /*enableAppExtensionRestrictions=*/true); + } if (auto *A = ParsedArgs.getLastArg(OPT_minimum_access_level)) { Options.MinimumAccessLevel = diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index f49329384add1..8b2acc1d3f6bc 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -21,6 +21,7 @@ #include "swift/AST/LazyResolver.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/PrettyStackTrace.h" +#include "swift/AST/SearchPathOptions.h" #include "swift/AST/Types.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/Platform.h" diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 276cece1a0087..67cc043cdb0e9 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -31,6 +31,7 @@ #include "swift/AST/MacroDefinition.h" #include "swift/AST/ParameterList.h" #include "swift/AST/ProtocolConformance.h" +#include "swift/AST/SILOptions.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeTransform.h" #include "swift/AST/Types.h" diff --git a/lib/SymbolGraphGen/AvailabilityMixin.cpp b/lib/SymbolGraphGen/AvailabilityMixin.cpp index 75a1c150e409b..ce8f6b8ec28a9 100644 --- a/lib/SymbolGraphGen/AvailabilityMixin.cpp +++ b/lib/SymbolGraphGen/AvailabilityMixin.cpp @@ -17,19 +17,18 @@ using namespace swift; using namespace symbolgraphgen; -namespace { -StringRef getDomain(const SemanticAvailableAttr &AvAttr) { +StringRef Availability::getDomainDescription(AvailabilityDomain Domain) { // FIXME: [avalailability] Move the definition of these strings into // AvailabilityDomain so that new domains are handled automatically. - if (AvAttr.getDomain().isPackageDescription()) + if (Domain.isPackageDescription()) return { "SwiftPM" }; - if (AvAttr.getDomain().isSwiftLanguageMode()) + if (Domain.isSwiftLanguageMode()) return { "Swift" }; // Platform-specific availability. - switch (AvAttr.getPlatform()) { + switch (Domain.getPlatformKind()) { case swift::PlatformKind::iOS: return { "iOS" }; case swift::PlatformKind::macCatalyst: @@ -73,12 +72,12 @@ StringRef getDomain(const SemanticAvailableAttr &AvAttr) { } llvm_unreachable("invalid platform kind"); } -} // end anonymous namespace Availability::Availability(const SemanticAvailableAttr &AvAttr) - : Domain(getDomain(AvAttr)), Introduced(AvAttr.getIntroduced()), - Deprecated(AvAttr.getDeprecated()), Obsoleted(AvAttr.getObsoleted()), - Message(AvAttr.getMessage()), Renamed(AvAttr.getRename()), + : Domain(getDomainDescription(AvAttr.getDomain())), + Introduced(AvAttr.getIntroduced()), Deprecated(AvAttr.getDeprecated()), + Obsoleted(AvAttr.getObsoleted()), Message(AvAttr.getMessage()), + Renamed(AvAttr.getRename()), IsUnconditionallyDeprecated(AvAttr.isUnconditionallyDeprecated()), IsUnconditionallyUnavailable(AvAttr.isUnconditionallyUnavailable()) { assert(!Domain.empty()); diff --git a/lib/SymbolGraphGen/AvailabilityMixin.h b/lib/SymbolGraphGen/AvailabilityMixin.h index 39fc82f007911..e66f8dea1da0c 100644 --- a/lib/SymbolGraphGen/AvailabilityMixin.h +++ b/lib/SymbolGraphGen/AvailabilityMixin.h @@ -49,6 +49,8 @@ struct Availability { /// If \c true, is unconditionally unavailable in this \c Domain. bool IsUnconditionallyUnavailable; + static StringRef getDomainDescription(AvailabilityDomain Domain); + Availability(const SemanticAvailableAttr &AvAttr); /// Update this availability from a duplicate @available diff --git a/lib/SymbolGraphGen/Symbol.cpp b/lib/SymbolGraphGen/Symbol.cpp index f5faae6d87801..6afb05f550af4 100644 --- a/lib/SymbolGraphGen/Symbol.cpp +++ b/lib/SymbolGraphGen/Symbol.cpp @@ -639,6 +639,94 @@ void Symbol::serializeLocationMixin(llvm::json::OStream &OS) const { } namespace { +/// Insert or merge a single Availability entry into a domain map, using +/// either parent-inheritance or duplicate-attribute rules. +void insertAvailability(Availability NewAvailability, + llvm::StringMap &Availabilities, + bool IsParent) { + if (NewAvailability.empty()) + return; + auto Existing = Availabilities.find(NewAvailability.Domain); + if (Existing != Availabilities.end()) { + // There are different rules for filling in missing components or replacing + // existing components from a parent's @available attribute compared to + // duplicate @available attributes on the same declaration. See the + // respective methods below for an explanation for the replacement/filling + // rules. + // FIXME: [availability] Use compiler's logic to synthesize availability. + // Some of this merge logic is out-of-sync with how the compiler determines + // availability when multiple attributes apply to the same platform. + if (IsParent) { + Existing->getValue().updateFromParent(NewAvailability); + } else { + Existing->getValue().updateFromDuplicate(NewAvailability); + } + } else { + // There are no availabilities for this domain yet, so either inherit the + // parent's in its entirety or set it from this declaration. + Availabilities.insert({NewAvailability.Domain, NewAvailability}); + } +} + +std::optional> +getPlatformsToExpand(SemanticAvailableAttr AvAttr) { + // For now, only expand platform availability for anyAppleOS attributes. + if (AvAttr.getDomain().contains( + AvailabilityDomain::forPlatform(PlatformKind::anyAppleOS))) { + static const PlatformKind ApplePlatforms[] = { + PlatformKind::macOS, + PlatformKind::iOS, + PlatformKind::watchOS, + PlatformKind::tvOS, + PlatformKind::visionOS, + }; + return ApplePlatforms; + } + + return {}; +} + +static bool +isAvailabilityDomainActive(AvailabilityDomain Domain, + std::optional ActivePlatform) { + if (!ActivePlatform) + return true; + + if (!Domain.isPlatform()) + return true; + + auto Platform = Domain.getPlatformKind(); + return Platform == *ActivePlatform || + inheritsAvailabilityFromPlatform(*ActivePlatform, Platform); +} + +/// Expands a single availability attribute into one or more Availability +/// structs. +void expandInferredAvailabilityAttr( + SemanticAvailableAttr AvAttr, SmallVectorImpl &Expanded, + std::optional ActivePlatform) { + if (auto Platforms = getPlatformsToExpand(AvAttr)) { + for (auto Platform : *Platforms) { + auto PlatformDomain = AvailabilityDomain::forPlatform(Platform); + if (!isAvailabilityDomainActive(PlatformDomain, ActivePlatform)) + continue; + + Availability InferredAvailability(AvAttr); + InferredAvailability.Domain = + Availability::getDomainDescription(PlatformDomain); + // FIXME: [availability] Versions should be remapped, too. + // Version remapping is unnecessary at the moment because only anyAppleOS + // availability gets expanded and anyAppleOS doesn't require version + // remapping (yet). + Expanded.push_back(InferredAvailability); + } + return; + } + + // Just convert the attribute directly. + Expanded.push_back(Availability(AvAttr)); +} + /// Get the availabilities for each domain on a declaration without walking /// up the parent hierarchy. /// @@ -649,48 +737,35 @@ namespace { /// duplicate \c \@available attributes on the same declaration. void getAvailabilities(const Decl *D, llvm::StringMap &Availabilities, - bool IsParent) { + bool IsParent, + std::optional ActivePlatform) { // DeclAttributes is a linked list in reverse order from where they // appeared in the source. Let's re-reverse them. - SmallVector AvAttrs; - for (auto Attr : D->getSemanticAvailableAttrs(/*includeInactive=*/true)) { + SmallVector AvAttrs; + for (auto Attr : D->getSemanticAvailableAttrs(/*includingInactive=*/true)) { + if (!isAvailabilityDomainActive(Attr.getDomain(), ActivePlatform)) + continue; + AvAttrs.push_back(Attr); } - std::reverse(AvAttrs.begin(), AvAttrs.end()); // Now go through them in source order. - for (auto AvAttr : AvAttrs) { - Availability NewAvailability(AvAttr); - if (NewAvailability.empty()) { - continue; - } - auto ExistingAvailability = Availabilities.find(NewAvailability.Domain); - if (ExistingAvailability != Availabilities.end()) { - // There are different rules for filling in missing components - // or replacing existing components from a parent's @available - // attribute compared to duplicate @available attributes on the - // same declaration. - // See the respective methods below for an explanation for the - // replacement/filling rules. - if (IsParent) { - ExistingAvailability->getValue().updateFromParent(NewAvailability); - } else { - ExistingAvailability->getValue().updateFromDuplicate(NewAvailability); - } - } else { - // There are no availabilities for this domain yet, so either - // inherit the parent's in its entirety or set it from this declaration. - Availabilities.insert(std::make_pair(NewAvailability.Domain, - NewAvailability)); - } + for (auto AvAttr : llvm::reverse(AvAttrs)) { + SmallVector ExpandedAvailabilities; + expandInferredAvailabilityAttr(AvAttr, ExpandedAvailabilities, + ActivePlatform); + for (auto &Avail : ExpandedAvailabilities) + insertAvailability(Avail, Availabilities, IsParent); } } -/// Get the availabilities of a declaration, considering all of its -/// parent context's except for the module. +/// Get the availabilities of a declaration, considering all of its parent +/// context's except for the module. If \p ActivePlatform is non-null, only +/// include availability relevant to the active platform. void getInheritedAvailabilities(const Decl *D, -llvm::StringMap &Availabilities) { - getAvailabilities(D, Availabilities, /*IsParent*/false); + llvm::StringMap &Availabilities, + std::optional ActivePlatform) { + getAvailabilities(D, Availabilities, /*IsParent*/ false, ActivePlatform); auto CurrentContext = D->getDeclContext(); while (CurrentContext) { @@ -698,7 +773,8 @@ llvm::StringMap &Availabilities) { if (isa(Parent)) { return; } - getAvailabilities(Parent, Availabilities, /*IsParent*/true); + getAvailabilities(Parent, Availabilities, /*IsParent*/ true, + ActivePlatform); } CurrentContext = CurrentContext->getParent(); } @@ -708,7 +784,8 @@ llvm::StringMap &Availabilities) { void Symbol::serializeAvailabilityMixin(llvm::json::OStream &OS) const { llvm::StringMap Availabilities; - getInheritedAvailabilities(D, Availabilities); + getInheritedAvailabilities(D, Availabilities, + Graph->Walker.Options.ActivePlatform); // If we were asked to filter the availability platforms for the output graph, // perform that filtering here. @@ -734,10 +811,18 @@ void Symbol::serializeAvailabilityMixin(llvm::json::OStream &OS) const { return; } - OS.attributeArray("availability", [&]{ - for (const auto &Availability : Availabilities) { - Availability.getValue().serialize(OS); - } + OS.attributeArray("availability", [&] { + // Sort the availability entries to ensure that they are emitted in a stable + // order. + SmallVector SortedAvailabilities; + for (const auto &A : Availabilities) + SortedAvailabilities.push_back(A.getValue()); + llvm::sort(SortedAvailabilities, + [](const Availability &A, const Availability &B) { + return A.Domain < B.Domain; + }); + for (const auto &A : SortedAvailabilities) + A.serialize(OS); }); } diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/Expansion.swift b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/Expansion.swift new file mode 100644 index 0000000000000..168f0ed035dac --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/Expansion.swift @@ -0,0 +1,93 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name Expansion -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name Expansion -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/Expansion.symbols.json + +// CHECK-LABEL: "symbols": [ +// CHECK-LABEL: "precise": "s:9Expansion1SV", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "iOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "message": "Everyone makes mistakes", +// CHECK-NEXT: "renamed": "S2" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "message": "Everyone makes mistakes", +// CHECK-NEXT: "renamed": "S2" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "tvOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "message": "Everyone makes mistakes", +// CHECK-NEXT: "renamed": "S2" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "visionOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "message": "Everyone makes mistakes", +// CHECK-NEXT: "renamed": "S2" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "watchOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "message": "Everyone makes mistakes", +// CHECK-NEXT: "renamed": "S2" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NOT: "domain": "Any Apple OS" + +@available(anyAppleOS, introduced: 26, deprecated: 26.2, obsoleted: 26.4, message: "Everyone makes mistakes", renamed: "S2") +public struct S {} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/InnerOverridesOuterPlatform.swift b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/InnerOverridesOuterPlatform.swift new file mode 100644 index 0000000000000..077c5520dbb4f --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/InnerOverridesOuterPlatform.swift @@ -0,0 +1,50 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name InnerOverridesOuterPlatform -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name InnerOverridesOuterPlatform -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/InnerOverridesOuterPlatform.symbols.json + +// CHECK-LABEL: "symbols": [ +// CHECK-LABEL: "precise": "s:27InnerOverridesOuterPlatform0C0V0A0V", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "iOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "tvOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "visionOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "watchOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] + +@available(macOS 26, *) +public struct Outer { + @available(anyAppleOS 26.4, *) + public struct Inner {} +} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/InnerPlatformOverridesOuter.swift b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/InnerPlatformOverridesOuter.swift new file mode 100644 index 0000000000000..d01bc24b8fb24 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/InnerPlatformOverridesOuter.swift @@ -0,0 +1,56 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name InnerPlatformOverridesOuter -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name InnerPlatformOverridesOuter -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/InnerPlatformOverridesOuter.symbols.json + +// CHECK-LABEL: "symbols": [ +// CHECK-LABEL: "precise": "s:27InnerPlatformOverridesOuter0D0V0A0V", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "iOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "tvOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "visionOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "watchOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] + +@available(anyAppleOS, introduced: 26) +public struct Outer { + @available(macOS, introduced: 26.4) + @available(iOS, introduced: 26.2, obsoleted: 26.4) + @available(watchOS 26.2, *) + @available(tvOS, deprecated) + public struct Inner {} +} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/OnlyActive.swift b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/OnlyActive.swift new file mode 100644 index 0000000000000..f7471bba422dd --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/OnlyActive.swift @@ -0,0 +1,20 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name OnlyActive -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name OnlyActive -I %t -pretty-print -active-platform-availability-only -output-dir %t +// RUN: %FileCheck %s --input-file %t/OnlyActive.symbols.json + +// REQUIRES: OS=macosx + +// CHECK-LABEL: "symbols": [ +// CHECK-LABEL: "precise": "s:10OnlyActive1SV", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] + +@available(anyAppleOS 26, *) +public struct S {} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/PlatformSupersedes.swift b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/PlatformSupersedes.swift new file mode 100644 index 0000000000000..c6be6ced29d10 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/AnyAppleOS/PlatformSupersedes.swift @@ -0,0 +1,54 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name PlatformSupersedes -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name PlatformSupersedes -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/PlatformSupersedes.symbols.json + +// CHECK-LABEL: "symbols": [ +// CHECK-LABEL: "precise": "s:18PlatformSupersedes1SV", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "iOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 2 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 26, +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: "minor": 4 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "tvOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: }, +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "visionOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// FIXME: [availability] watchOS introduction should be 11 +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "watchOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 26 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] + +@available(anyAppleOS, introduced: 26) +@available(macOS, introduced: 26.4) +@available(iOS, introduced: 26.2, obsoleted: 26.4) +@available(watchOS 11, *) +@available(tvOS, deprecated) +public struct S {} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift index 157ea906da57d..82705171f153a 100644 --- a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift @@ -13,13 +13,13 @@ public func foo() {} // CHECK-LABEL: "precise": "s:15MessageLastWins3fooyyF", // CHECK: "availability": [ // CHECK-NEXT: { -// CHECK-NEXT: "domain": "macOS", -// CHECK-NEXT: "message": "second", +// CHECK-NEXT: "domain": "iOS", +// CHECK-NEXT: "message": "iOS", // CHECK-NEXT: "isUnconditionallyDeprecated": true // CHECK-NEXT: }, // CHECK-NEXT: { -// CHECK-NEXT: "domain": "iOS", -// CHECK-NEXT: "message": "iOS", +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "message": "second", // CHECK-NEXT: "isUnconditionallyDeprecated": true // CHECK-NEXT: } // CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/OnlyActive.swift b/test/SymbolGraph/Symbols/Mixins/Availability/OnlyActive.swift new file mode 100644 index 0000000000000..f078bb0ac0687 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/OnlyActive.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name OnlyActive -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name OnlyActive -I %t -pretty-print -active-platform-availability-only -output-dir %t +// RUN: %FileCheck %s --input-file %t/OnlyActive.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS 10.9, iOS 8.0, watchOS 8.0, tvOS 8.0, visionOS 1.0, *) +public struct S {} + +// CHECK-NOT: iOS +// CHECK: "domain": "macOS" +// CHECK-NOT: tvOS +// CHECK-NOT: visionOS +// CHECK-NOT: watchOS + diff --git a/unittests/AST/TestContext.h b/unittests/AST/TestContext.h index f830b3e0d34d7..7ddcf3427fad1 100644 --- a/unittests/AST/TestContext.h +++ b/unittests/AST/TestContext.h @@ -13,9 +13,13 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/Module.h" +#include "swift/AST/SILOptions.h" +#include "swift/AST/SearchPathOptions.h" #include "swift/AST/SourceFile.h" +#include "swift/Basic/CASOptions.h" #include "swift/Basic/LangOptions.h" #include "swift/Basic/SourceManager.h" +#include "swift/Serialization/SerializationOptions.h" #include "swift/SymbolGraphGen/SymbolGraphOptions.h" #include "llvm/TargetParser/Host.h" diff --git a/unittests/ClangImporter/ClangImporterTests.cpp b/unittests/ClangImporter/ClangImporterTests.cpp index b643eb6b59b50..273fbb32420d5 100644 --- a/unittests/ClangImporter/ClangImporterTests.cpp +++ b/unittests/ClangImporter/ClangImporterTests.cpp @@ -1,5 +1,6 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticEngine.h" +#include "swift/AST/SILOptions.h" #include "swift/AST/SearchPathOptions.h" #include "swift/Basic/CASOptions.h" #include "swift/Basic/Defer.h" @@ -7,6 +8,7 @@ #include "swift/Basic/LangOptions.h" #include "swift/Basic/SourceManager.h" #include "swift/ClangImporter/ClangImporter.h" +#include "swift/Serialization/SerializationOptions.h" #include "swift/SymbolGraphGen/SymbolGraphOptions.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/FileSystem.h" diff --git a/unittests/Sema/SemaFixture.h b/unittests/Sema/SemaFixture.h index bda2b433b4da2..f42993702a8aa 100644 --- a/unittests/Sema/SemaFixture.h +++ b/unittests/Sema/SemaFixture.h @@ -13,13 +13,17 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/Module.h" +#include "swift/AST/SILOptions.h" +#include "swift/AST/SearchPathOptions.h" #include "swift/AST/SourceFile.h" #include "swift/AST/Type.h" #include "swift/AST/Types.h" +#include "swift/Basic/CASOptions.h" #include "swift/Basic/LangOptions.h" #include "swift/Basic/Platform.h" #include "swift/Basic/SourceManager.h" #include "swift/Sema/ConstraintSystem.h" +#include "swift/Serialization/SerializationOptions.h" #include "swift/SymbolGraphGen/SymbolGraphOptions.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h"