From e1f2e25ed52ec7afa7f227bbaf7ff9540d18818b Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Wed, 4 Oct 2023 23:13:23 -0700 Subject: [PATCH 1/3] Frontend: Introduce -emit-api-descriptor flag. An "API descriptor" file is JSON describing the externally accessible symbols of a module and metadata associated with those symbols like availability and SPI status. This output was previously only generated by the `swift-api-extract` alias of `swift-frontend`, which is desgined to take an already built module as input. Post-processing a built module to extract this information is inefficient because the module and the module's dependencies need to be deserialized in order to visit the entire AST. We can generate this output more efficiently as a supplementary output of the -emit-module job that originally produced the module (since the AST is already available in-memory). The -emit-api-descriptor flag can be used to request this output. This change lays the groundwork by introducing frontend flags. Follow up changes are needed to make API descriptor emission during -emit-module functional. Part of rdar://110916764. --- include/swift/AST/DiagnosticsFrontend.def | 4 +- include/swift/Basic/FileTypes.def | 1 + .../swift/Basic/SupplementaryOutputPaths.def | 3 ++ include/swift/Frontend/Frontend.h | 5 +++ .../swift/Frontend/FrontendInputsAndOutputs.h | 1 + include/swift/Frontend/FrontendOptions.h | 1 + include/swift/Option/Options.td | 14 ++++++- lib/Basic/FileTypes.cpp | 3 ++ lib/Driver/Driver.cpp | 1 + lib/Driver/ToolChains.cpp | 2 + .../ArgsToFrontendOptionsConverter.cpp | 5 +++ .../ArgsToFrontendOutputsConverter.cpp | 11 ++++- lib/Frontend/Frontend.cpp | 8 ++++ lib/Frontend/FrontendInputsAndOutputs.cpp | 6 +++ lib/Frontend/FrontendOptions.cpp | 42 +++++++++++++++++++ lib/FrontendTool/FrontendTool.cpp | 34 +++++++++++++++ .../supplementary-output-support.swift | 3 ++ 17 files changed, 141 insertions(+), 3 deletions(-) diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index d6ec2d481c926..a6896a5e82408 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -152,7 +152,9 @@ ERROR(error_mode_cannot_emit_module_summary,none, ERROR(error_mode_cannot_emit_symbol_graph,none, "this mode does not support emitting symbol graph files", ()) ERROR(error_mode_cannot_emit_abi_descriptor,none, - "this mode does not support emitting ABI descriptor", ()) + "this mode does not support emitting ABI descriptor files", ()) +ERROR(error_mode_cannot_emit_api_descriptor,none, + "this mode does not support emitting API descriptor files", ()) ERROR(error_mode_cannot_emit_const_values,none, "this mode does not support emitting extracted const values", ()) ERROR(error_mode_cannot_emit_module_semantic_info,none, diff --git a/include/swift/Basic/FileTypes.def b/include/swift/Basic/FileTypes.def index 4a68242e5e1b8..a8245b3cd2408 100644 --- a/include/swift/Basic/FileTypes.def +++ b/include/swift/Basic/FileTypes.def @@ -98,6 +98,7 @@ TYPE("pch", PCH, "pch", "") TYPE("none", Nothing, "", "") TYPE("abi-baseline-json", SwiftABIDescriptor, "abi.json", "") +TYPE("api-json", SwiftAPIDescriptor, "", "") TYPE("fixit", SwiftFixIt, "", "") TYPE("module-semantic-info", ModuleSemanticInfo, "", "") TYPE("cached-diagnostics", CachedDiagnostics, "", "") diff --git a/include/swift/Basic/SupplementaryOutputPaths.def b/include/swift/Basic/SupplementaryOutputPaths.def index c9c8a44a8ab2c..8b566de3fb20b 100644 --- a/include/swift/Basic/SupplementaryOutputPaths.def +++ b/include/swift/Basic/SupplementaryOutputPaths.def @@ -143,6 +143,9 @@ OUTPUT(ModuleSummaryOutputPath, TY_SwiftModuleSummaryFile) /// The output path to generate ABI baseline. OUTPUT(ABIDescriptorOutputPath, TY_SwiftABIDescriptor) +/// The output path to the module's API description. +OUTPUT(APIDescriptorOutputPath, TY_SwiftAPIDescriptor) + /// The output path for extracted compile-time-known value information OUTPUT(ConstValuesOutputPath, TY_ConstValues) diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index aba24b77283bb..910315d93f8fb 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -428,6 +428,11 @@ class CompilerInvocation { std::string getModuleInterfaceOutputPathForWholeModule() const; std::string getPrivateModuleInterfaceOutputPathForWholeModule() const; + /// APIDescriptorPath only makes sense in whole module compilation mode, + /// so return the APIDescriptorPath when in that mode and fail an assert + /// if not in that mode. + std::string getAPIDescriptorPathForWholeModule() const; + public: /// Given the current configuration of this frontend invocation, a set of /// supplementary output paths, and a module, compute the appropriate set of diff --git a/include/swift/Frontend/FrontendInputsAndOutputs.h b/include/swift/Frontend/FrontendInputsAndOutputs.h index 166c461cd53e6..09a6c96323a96 100644 --- a/include/swift/Frontend/FrontendInputsAndOutputs.h +++ b/include/swift/Frontend/FrontendInputsAndOutputs.h @@ -265,6 +265,7 @@ class FrontendInputsAndOutputs { bool hasModuleInterfaceOutputPath() const; bool hasPrivateModuleInterfaceOutputPath() const; bool hasABIDescriptorOutputPath() const; + bool hasAPIDescriptorOutputPath() const; bool hasConstValuesOutputPath() const; bool hasModuleSemanticInfoOutputPath() const; bool hasModuleSummaryOutputPath() const; diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 7c90061dc178d..b14ca2dfb67f8 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -569,6 +569,7 @@ class FrontendOptions { static bool canActionEmitModuleSummary(ActionType); static bool canActionEmitInterface(ActionType); static bool canActionEmitABIDescriptor(ActionType); + static bool canActionEmitAPIDescriptor(ActionType); static bool canActionEmitConstValues(ActionType); static bool canActionEmitModuleSemanticInfo(ActionType); diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 9c41bfed7c0e7..3a5793f71a8ff 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -626,7 +626,19 @@ def emit_const_values : def emit_const_values_path : Separate<["-"], "emit-const-values-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, SupplementaryOutput, CacheInvariant]>, - MetaVarName<"">, HelpText<"Emit the extracted compile-time known values to ">; + MetaVarName<"">, + HelpText<"Emit the extracted compile-time known values to ">; + +def emit_api_descriptor : + Flag<["-"], "emit-api-descriptor">, + Flags<[NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, + HelpText<"Output a JSON file describing the module's API">; +def emit_api_descriptor_path : + Separate<["-"], "emit-api-descriptor-path">, + Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, + SupplementaryOutput, CacheInvariant]>, + MetaVarName<"">, + HelpText<"Output a JSON file describing the module's API to ">; def emit_objc_header : Flag<["-"], "emit-objc-header">, Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, diff --git a/lib/Basic/FileTypes.cpp b/lib/Basic/FileTypes.cpp index 3a63ecb46b833..556cb2d319554 100644 --- a/lib/Basic/FileTypes.cpp +++ b/lib/Basic/FileTypes.cpp @@ -86,6 +86,7 @@ bool file_types::isTextual(ID Id) { case file_types::TY_JSONDependencies: case file_types::TY_JSONFeatures: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_SwiftAPIDescriptor: case file_types::TY_ConstValues: return true; case file_types::TY_Image: @@ -164,6 +165,7 @@ bool file_types::isAfterLLVM(ID Id) { case file_types::TY_JSONFeatures: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_SwiftAPIDescriptor: case file_types::TY_ConstValues: case file_types::TY_SwiftFixIt: case file_types::TY_ModuleSemanticInfo: @@ -220,6 +222,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) { case file_types::TY_JSONFeatures: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_SwiftAPIDescriptor: case file_types::TY_ConstValues: case file_types::TY_SwiftFixIt: case file_types::TY_ModuleSemanticInfo: diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index c3dc3aa283897..4335a6fdc9598 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2090,6 +2090,7 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, case file_types::TY_JSONDependencies: case file_types::TY_JSONFeatures: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_SwiftAPIDescriptor: case file_types::TY_ConstValues: case file_types::TY_SwiftFixIt: case file_types::TY_ModuleSemanticInfo: diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index b01044d4f02ae..718b14354be14 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -733,6 +733,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const { case file_types::TY_SwiftOverlayFile: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_SwiftAPIDescriptor: case file_types::TY_ConstValues: case file_types::TY_SwiftFixIt: case file_types::TY_ModuleSemanticInfo: @@ -997,6 +998,7 @@ ToolChain::constructInvocation(const BackendJobAction &job, case file_types::TY_SwiftOverlayFile: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_SwiftAPIDescriptor: case file_types::TY_ConstValues: case file_types::TY_SwiftFixIt: case file_types::TY_ModuleSemanticInfo: diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index ffe99cf61339d..2ec677d71c2a4 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -765,6 +765,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths() Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_abi_descriptor); return true; } + if (!FrontendOptions::canActionEmitAPIDescriptor(Opts.RequestedAction) && + Opts.InputsAndOutputs.hasAPIDescriptorOutputPath()) { + Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_api_descriptor); + return true; + } if (!FrontendOptions::canActionEmitConstValues(Opts.RequestedAction) && Opts.InputsAndOutputs.hasConstValuesOutputPath()) { Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_const_values); diff --git a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp index 9ad436912bfe7..9b8fb60d39c04 100644 --- a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp @@ -331,6 +331,8 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments() options::OPT_emit_module_summary_path); auto abiDescriptorOutput = getSupplementaryFilenamesFromArguments( options::OPT_emit_abi_descriptor_path); + auto apiDescriptorOutput = getSupplementaryFilenamesFromArguments( + options::OPT_emit_api_descriptor_path); auto constValuesOutput = getSupplementaryFilenamesFromArguments( options::OPT_emit_const_values_path); auto moduleSemanticInfoOutput = getSupplementaryFilenamesFromArguments( @@ -365,6 +367,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments() sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i]; sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[i]; sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[i]; + sop.APIDescriptorOutputPath = (*apiDescriptorOutput)[i]; sop.ConstValuesOutputPath = (*constValuesOutput)[i]; sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[i]; sop.YAMLOptRecordPath = (*optRecordOutput)[i]; @@ -475,8 +478,13 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput( // There is no non-path form of -emit-abi-descriptor-path auto ABIDescriptorOutputPath = pathsFromArguments.ABIDescriptorOutputPath; + + // There is no non-path form of -emit-api-descriptor-path + auto APIDescriptorOutputPath = pathsFromArguments.APIDescriptorOutputPath; + // There is no non-path form of -emit-module-semantic-info-path - auto ModuleSemanticInfoOutputPath = pathsFromArguments.ModuleSemanticInfoOutputPath; + auto ModuleSemanticInfoOutputPath = + pathsFromArguments.ModuleSemanticInfoOutputPath; ID emitModuleOption; std::string moduleExtension; @@ -513,6 +521,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput( sop.ModuleSourceInfoOutputPath = moduleSourceInfoOutputPath; sop.ModuleSummaryOutputPath = moduleSummaryOutputPath; sop.ABIDescriptorOutputPath = ABIDescriptorOutputPath; + sop.APIDescriptorOutputPath = APIDescriptorOutputPath; sop.ConstValuesOutputPath = constValuesOutputPath; sop.ModuleSemanticInfoOutputPath = ModuleSemanticInfoOutputPath; sop.YAMLOptRecordPath = YAMLOptRecordPath; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 610b5f30ab072..23387bbdbb32c 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -165,6 +165,14 @@ CompilerInvocation::getPrivateModuleInterfaceOutputPathForWholeModule() const { .SupplementaryOutputs.PrivateModuleInterfaceOutputPath; } +std::string CompilerInvocation::getAPIDescriptorPathForWholeModule() const { + assert( + getFrontendOptions().InputsAndOutputs.isWholeModule() && + "APIDescriptorPath only makes sense when the whole module can be seen"); + return getPrimarySpecificPathsForAtMostOnePrimary() + .SupplementaryOutputs.APIDescriptorOutputPath; +} + SerializationOptions CompilerInvocation::computeSerializationOptions( const SupplementaryOutputPaths &outs, const ModuleDecl *module) const { const FrontendOptions &opts = getFrontendOptions(); diff --git a/lib/Frontend/FrontendInputsAndOutputs.cpp b/lib/Frontend/FrontendInputsAndOutputs.cpp index 2d5227522e397..d41d92cec23e0 100644 --- a/lib/Frontend/FrontendInputsAndOutputs.cpp +++ b/lib/Frontend/FrontendInputsAndOutputs.cpp @@ -511,6 +511,12 @@ bool FrontendInputsAndOutputs::hasABIDescriptorOutputPath() const { return outs.ABIDescriptorOutputPath; }); } +bool FrontendInputsAndOutputs::hasAPIDescriptorOutputPath() const { + return hasSupplementaryOutputPath( + [](const SupplementaryOutputPaths &outs) -> const std::string & { + return outs.APIDescriptorOutputPath; + }); +} bool FrontendInputsAndOutputs::hasConstValuesOutputPath() const { return hasSupplementaryOutputPath( [](const SupplementaryOutputPaths &outs) -> const std::string & { diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index eb381672154b4..a449922eb288e 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -743,6 +743,48 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) { llvm_unreachable("unhandled action"); } +bool FrontendOptions::canActionEmitAPIDescriptor(ActionType action) { + switch (action) { + case ActionType::NoneAction: + case ActionType::Parse: + case ActionType::DumpParse: + case ActionType::DumpInterfaceHash: + case ActionType::DumpAST: + case ActionType::PrintAST: + case ActionType::PrintASTDecl: + case ActionType::EmitImportedModules: + case ActionType::EmitPCH: + case ActionType::DumpScopeMaps: + case ActionType::DumpTypeRefinementContexts: + case ActionType::DumpTypeInfo: + case ActionType::EmitSILGen: + case ActionType::EmitSIBGen: + case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: + case ActionType::Immediate: + case ActionType::REPL: + case ActionType::EmitPCM: + case ActionType::DumpPCM: + case ActionType::ScanDependencies: + case ActionType::PrintFeature: + return false; + case ActionType::ResolveImports: + case ActionType::Typecheck: + case ActionType::MergeModules: + case ActionType::EmitModuleOnly: + case ActionType::EmitSIL: + case ActionType::EmitSIB: + case ActionType::EmitIRGen: + case ActionType::EmitIR: + case ActionType::EmitBC: + case ActionType::EmitAssembly: + case ActionType::EmitObject: + case ActionType::PrintVersion: + return true; + } + llvm_unreachable("unhandled action"); +} + bool FrontendOptions::doesActionProduceOutput(ActionType action) { switch (action) { case ActionType::Parse: diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index afbc57cdf2f37..04c3a18ac3fe5 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -809,6 +809,36 @@ static bool writeTBDIfNeeded(CompilerInstance &Instance) { Instance.getOutputBackend(), tbdOpts); } +static bool writeAPIDescriptor(ModuleDecl *M, StringRef OutputPath, + llvm::vfs::OutputBackend &Backend, + bool PrettyPrinted) { + return withOutputPath(M->getDiags(), Backend, OutputPath, + [&](raw_ostream &OS) -> bool { + writeAPIJSONFile(M, OS, PrettyPrinted); + return false; + }); +} + +static bool writeAPIDescriptorIfNeeded(CompilerInstance &Instance) { + const auto &Invocation = Instance.getInvocation(); + const auto &frontendOpts = Invocation.getFrontendOptions(); + if (!frontendOpts.InputsAndOutputs.hasAPIDescriptorOutputPath()) + return false; + + if (!frontendOpts.InputsAndOutputs.isWholeModule()) { + Instance.getDiags().diagnose( + SourceLoc(), diag::api_descriptor_only_supported_in_whole_module); + return false; + } + + const std::string &APIDescriptorPath = + Invocation.getAPIDescriptorPathForWholeModule(); + + // FIXME: Need a frontend flag for pretty printing + return writeAPIDescriptor(Instance.getMainModule(), APIDescriptorPath, + Instance.getOutputBackend(), true); +} + static bool performCompileStepsPostSILGen(CompilerInstance &Instance, std::unique_ptr SM, ModuleOrSourceFile MSF, @@ -975,6 +1005,10 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs( hadAnyError |= writeTBDIfNeeded(Instance); } + { + hadAnyError |= writeAPIDescriptorIfNeeded(Instance); + } + { hadAnyError |= writeModuleSemanticInfoIfNeeded(Instance); } diff --git a/test/Frontend/supplementary-output-support.swift b/test/Frontend/supplementary-output-support.swift index 5f9dc91e807b8..98146963b534d 100644 --- a/test/Frontend/supplementary-output-support.swift +++ b/test/Frontend/supplementary-output-support.swift @@ -36,3 +36,6 @@ // RUN: not %target-swift-frontend -parse -emit-const-values-path %t %s 2>&1 | %FileCheck -check-prefix=PARSE_NO_CONST_VALUES %s // PARSE_NO_CONST_VALUES: error: this mode does not support emitting extracted const values{{$}} + +// RUN: not %target-swift-frontend -parse -emit-api-descriptor-path %t %s 2>&1 | %FileCheck -check-prefix=PARSE_NO_API_DESCRIPTOR %s +// PARSE_NO_API_DESCRIPTOR: error: this mode does not support emitting API descriptor files{{$}} From e91580bf0e8550e773ecae701da40f9804816686 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Thu, 5 Oct 2023 09:42:04 -0700 Subject: [PATCH 2/3] TBDGen: Teach APIGenRecorder to emit API descriptors during -emit-module. Make the changes to APIGenRecorder that are necessary to make it capable of emitting API descriptors during -emit-module jobs. The output in this mode differs from the output when run on an existing module in a couple of important ways: - The value for the `file` key in the descriptor JSON is now the path to the source file that defines the declaration responsible for the symbol. In `swift-api-extract` mode, the value for this key is the path to the module or swiftinterface which is unavailable during an -emit-module job since the module is usually not being emitted to its final installed location. - Some additional symbols may be included in the API descriptor JSON because more of the AST is available when emitting the module. Resolves rdar://110916764 --- include/swift/AST/DiagnosticsFrontend.def | 4 + lib/IRGen/TBDGen.cpp | 52 ++++-- test/APIJSON/apigen.swift | 186 +++++++++++++++------- test/APIJSON/extension.swift | 27 ++-- test/APIJSON/non-objc-class.swift | 30 ++-- test/APIJSON/non-swift-api.swift | 1 + test/APIJSON/spi.swift | 104 +++++++----- test/APIJSON/struct.swift | 18 ++- 8 files changed, 283 insertions(+), 139 deletions(-) diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index a6896a5e82408..ebded4d931589 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -315,6 +315,10 @@ ERROR(tbd_not_supported_with_cmo,none, "Test-Based InstallAPI (TBD) is not support with cross-module-optimization", ()) +WARNING(api_descriptor_only_supported_in_whole_module,none, + "API descriptor generation is only supported when the whole module can be seen", + ()) + ERROR(previous_installname_map_missing,none, "cannot open previous install name map from %0", (StringRef)) diff --git a/lib/IRGen/TBDGen.cpp b/lib/IRGen/TBDGen.cpp index 958100d6fdc90..0d0d13a0a1f97 100644 --- a/lib/IRGen/TBDGen.cpp +++ b/lib/IRGen/TBDGen.cpp @@ -664,8 +664,13 @@ class APIGenRecorder final : public APIRecorder { public: APIGenRecorder(apigen::API &api, ModuleDecl *module) : api(api), module(module) { - const auto &MainFile = module->getMainFile(FileUnitKind::SerializedAST); - moduleLoc = apigen::APILoc(MainFile.getModuleDefiningPath().str(), 0, 0); + // If we're working with a serialized module, make the default location + // for symbols the path to the binary module. + if (FileUnit *MainFile = module->getFiles().front()) { + if (MainFile->getKind() == FileUnitKind::SerializedAST) + defaultLoc = + apigen::APILoc(MainFile->getModuleDefiningPath().str(), 0, 0); + } } ~APIGenRecorder() {} @@ -682,7 +687,7 @@ class APIGenRecorder final : public APIRecorder { access = apigen::APIAccess::Private; } - api.addSymbol(symbol, moduleLoc, apigen::APILinkage::Exported, + api.addSymbol(symbol, getAPILocForDecl(decl), apigen::APILinkage::Exported, apigen::APIFlags::None, access, availability); } @@ -700,12 +705,12 @@ class APIGenRecorder final : public APIRecorder { apigen::APIAvailability availability; bool isInstanceMethod = true; auto access = apigen::APIAccess::Public; - if (method.hasDecl()) { - availability = getAvailability(method.getDecl()); - if (method.getDecl()->getDescriptiveKind() == - DescriptiveDeclKind::ClassMethod) + auto decl = method.hasDecl() ? method.getDecl() : nullptr; + if (decl) { + availability = getAvailability(decl); + if (decl->getDescriptiveKind() == DescriptiveDeclKind::ClassMethod) isInstanceMethod = false; - if (isSPI(method.getDecl())) + if (isSPI(decl)) access = apigen::APIAccess::Private; } @@ -716,11 +721,27 @@ class APIGenRecorder final : public APIRecorder { record = addOrGetObjCCategory(ext); if (record) - api.addObjCMethod(record, name, moduleLoc, access, isInstanceMethod, - false, availability); + api.addObjCMethod(record, name, getAPILocForDecl(decl), access, + isInstanceMethod, false, availability); } private: + apigen::APILoc getAPILocForDecl(const Decl *decl) { + if (!decl) + return defaultLoc; + + SourceLoc loc = decl->getLoc(); + if (!loc.isValid()) + return defaultLoc; + + auto &SM = decl->getASTContext().SourceMgr; + unsigned line, col; + std::tie(line, col) = SM.getPresumedLineAndColumnForLoc(loc); + auto displayName = SM.getDisplayNameForLoc(loc); + + return apigen::APILoc(std::string(displayName), line, col); + } + /// Follow the naming schema that IRGen uses for Categories (see /// ClassDataBuilder). using CategoryNameKey = std::pair; @@ -776,8 +797,8 @@ class APIGenRecorder final : public APIRecorder { decl->getFormalAccess() == AccessLevel::Public && decl->isObjC() ? apigen::APILinkage::Exported : apigen::APILinkage::Internal; - auto cls = api.addObjCClass(name, linkage, moduleLoc, access, availability, - superCls); + auto cls = api.addObjCClass(name, linkage, getAPILocForDecl(decl), access, + availability, superCls); classMap.try_emplace(decl, cls); return cls; } @@ -809,15 +830,16 @@ class APIGenRecorder final : public APIRecorder { decl->getMaxAccessLevel() == AccessLevel::Public ? apigen::APILinkage::Exported : apigen::APILinkage::Internal; - auto category = api.addObjCCategory(nameBuffer, linkage, moduleLoc, access, - availability, interface); + auto category = + api.addObjCCategory(nameBuffer, linkage, getAPILocForDecl(decl), access, + availability, interface); categoryMap.try_emplace(decl, category); return category; } apigen::API &api; ModuleDecl *module; - apigen::APILoc moduleLoc; + apigen::APILoc defaultLoc; llvm::DenseMap classMap; llvm::DenseMap diff --git a/test/APIJSON/apigen.swift b/test/APIJSON/apigen.swift index 432f97ad33b9a..6a9bee66d1e77 100644 --- a/test/APIJSON/apigen.swift +++ b/test/APIJSON/apigen.swift @@ -2,7 +2,8 @@ // RUN: %empty-directory(%t) // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s +// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK,CHECK-EXTRACT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT import Foundation @@ -52,306 +53,360 @@ public var myGlobalVar: Int = 42 // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule10myFunctionSiyF", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule11myFunction1yyF", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "obsoleted": "10.9" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule11myFunction2yyF", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "unavailable": true // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivM", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivg", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivs", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestC7method1yyFTj", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestC7method1yyFTq", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestC7method2yyFZTj", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.14" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestC7method2yyFZTq", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.14" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestC7nonObjcyyFTj", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestC7nonObjcyyFTq", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCACycfC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCACycfc", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCMa", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCMn", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCMo", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCMu", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCN", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule4TestCfD", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2CMa", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2CMm", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2CMn", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2CMo", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, +// CHECK-EMIT-NEXT: { +// CHECK-EMIT-NEXT: "name": "_$s8MyModule5Test2CMu", +// CHECK-EMIT-NEXT: "access": "public", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", +// CHECK-EMIT-NEXT: "linkage": "exported" +// CHECK-EMIT-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2CN", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2CfD", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test2Cfd", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3C7fromIntACSi_tcfC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3C7fromIntACSi_tcfCTj", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3C7fromIntACSi_tcfCTq", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3C7fromIntACSi_tcfc", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CACycfC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CACycfc", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CMa", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CMn", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CMo", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CMu", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CN", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CfD", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CyACSfcfC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule5Test3CyACSfcfc", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCACycfC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCACycfc", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCMa", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCMn", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCMo", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCN", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule7DerivedCfD", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: } // CHECK-NEXT: ], @@ -359,7 +414,8 @@ public var myGlobalVar: Int = 42 // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule4Test", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13", // CHECK-NEXT: "super": "NSObject", @@ -367,19 +423,22 @@ public var myGlobalVar: Int = 42 // CHECK-NEXT: { // CHECK-NEXT: "name": "method1", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "init", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "method2", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "introduced": "10.14" // CHECK-NEXT: } // CHECK-NEXT: ] @@ -387,24 +446,28 @@ public var myGlobalVar: Int = 42 // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule5Test3", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "super": "NSObject", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "init", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "initFromInt:", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "init:", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -412,7 +475,8 @@ public var myGlobalVar: Int = 42 // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule7Derived", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13", // CHECK-NEXT: "super": "_TtC8MyModule4Test", @@ -420,12 +484,14 @@ public var myGlobalVar: Int = 42 // CHECK-NEXT: { // CHECK-NEXT: "name": "method1", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "init", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/apigen.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] diff --git a/test/APIJSON/extension.swift b/test/APIJSON/extension.swift index f2f919d9c92a9..4781b359ec301 100644 --- a/test/APIJSON/extension.swift +++ b/test/APIJSON/extension.swift @@ -2,7 +2,8 @@ // RUN: %empty-directory(%t) // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s +// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK,CHECK-EXTRACT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT import Foundation @@ -47,14 +48,16 @@ extension B { // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule1B", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "super": "NSObject", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "init", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -64,14 +67,16 @@ extension B { // CHECK-NEXT: { // CHECK-NEXT: "name": "MyModule", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "interface": "NSDictionary", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "__custom_name:", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -79,14 +84,16 @@ extension B { // CHECK-NEXT: { // CHECK-NEXT: "name": "MyModule", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "interface": "_TtC8MyModule1B", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "run", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -94,14 +101,16 @@ extension B { // CHECK-NEXT: { // CHECK-NEXT: "name": "MyModule1", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "interface": "_TtC8MyModule1B", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "fun", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/extension.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] diff --git a/test/APIJSON/non-objc-class.swift b/test/APIJSON/non-objc-class.swift index 8d97fc0a303be..fe7688bca5b5f 100644 --- a/test/APIJSON/non-objc-class.swift +++ b/test/APIJSON/non-objc-class.swift @@ -2,7 +2,8 @@ // RUN: %empty-directory(%t) // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s +// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s -check-prefixes=CHECK,CHECK-EXTRACT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT import Foundation @@ -30,19 +31,22 @@ public class NonObjC3 { // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule7NonObjC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift", // CHECK-NEXT: "linkage": "internal", // CHECK-NEXT: "super": "", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "init", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "testMethod", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -50,14 +54,16 @@ public class NonObjC3 { // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule8NonObjC1", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift", // CHECK-NEXT: "linkage": "internal", // CHECK-NEXT: "super": "", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "testMethod", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -65,14 +71,16 @@ public class NonObjC3 { // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule8NonObjC2", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift", // CHECK-NEXT: "linkage": "internal", // CHECK-NEXT: "super": "", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "testMethod", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] @@ -80,14 +88,16 @@ public class NonObjC3 { // CHECK-NEXT: { // CHECK-NEXT: "name": "_TtC8MyModule8NonObjC3", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift", // CHECK-NEXT: "linkage": "internal", // CHECK-NEXT: "super": "", // CHECK-NEXT: "instanceMethods": [ // CHECK-NEXT: { // CHECK-NEXT: "name": "init", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface" +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/non-objc-class.swift" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "classMethods": [] diff --git a/test/APIJSON/non-swift-api.swift b/test/APIJSON/non-swift-api.swift index fe29388458e16..e186b991c0fa8 100644 --- a/test/APIJSON/non-swift-api.swift +++ b/test/APIJSON/non-swift-api.swift @@ -5,6 +5,7 @@ // RUN: cp %S/Inputs/NativeDep.h %t/NativeDep.framework/Headers // RUN: %target-swift-frontend %s -parse-as-library -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5 +// RUN: %target-swift-frontend %s -parse-as-library -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s /// Check that both swiftmodule and swiftinterface can be used as input. // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t/cache -F %t | %FileCheck %s diff --git a/test/APIJSON/spi.swift b/test/APIJSON/spi.swift index 30e43916ec772..48b9fb2655bb9 100644 --- a/test/APIJSON/spi.swift +++ b/test/APIJSON/spi.swift @@ -4,8 +4,9 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 -// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefix=CHECK-SPI +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -parse-as-library -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 +// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK-SPI,CHECK-SPI-EXTRACT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -parse-as-library -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK-SPI,CHECK-SPI-EMIT import Foundation @@ -132,174 +133,195 @@ public func spiAvailableFunc() {} // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassC9spiMethodyyFTj", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassC9spiMethodyyFTq", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCACycfC", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCACycfc", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCMa", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCMn", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCMo", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCMu", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCN", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCfD", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2C18spiAvailableMethodyyFTj", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported", // CHECK-SPI-NEXT: "introduced": "10.10" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2C18spiAvailableMethodyyFTq", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported", // CHECK-SPI-NEXT: "introduced": "10.10" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2C9spiMethodyyFTj", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2C9spiMethodyyFTq", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CACycfC", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CACycfc", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CMa", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CMn", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CMo", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CMu", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CN", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule0A6Class2CfD", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule15newUnprovenFuncyyF", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_$s8MyModule16spiAvailableFuncyyF", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported", // CHECK-SPI-NEXT: "introduced": "10.10" -// CHECK-SPI-NEXT: }, -// CHECK-SPI-NEXT: { -// CHECK-SPI-NEXT: "name": "_main", -// CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", -// CHECK-SPI-NEXT: "linkage": "exported" // CHECK-SPI-NEXT: } // CHECK-SPI-NEXT: ], // CHECK-SPI-NEXT: "interfaces": [ // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_TtC8MyModule7MyClass", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported", // CHECK-SPI-NEXT: "super": "NSObject", // CHECK-SPI-NEXT: "instanceMethods": [ // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "spiMethod", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "init", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift" // CHECK-SPI-NEXT: } // CHECK-SPI-NEXT: ], // CHECK-SPI-NEXT: "classMethods": [] @@ -307,25 +329,29 @@ public func spiAvailableFunc() {} // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "_TtC8MyModule8MyClass2", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "linkage": "exported", // CHECK-SPI-NEXT: "super": "NSObject", // CHECK-SPI-NEXT: "instanceMethods": [ // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "spiMethod", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "spiAvailableMethod", // CHECK-SPI-NEXT: "access": "private", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule", +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift", // CHECK-SPI-NEXT: "introduced": "10.10" // CHECK-SPI-NEXT: }, // CHECK-SPI-NEXT: { // CHECK-SPI-NEXT: "name": "init", // CHECK-SPI-NEXT: "access": "public", -// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EXTRACT-NEXT: "file": "/@input/MyModule.swiftmodule" +// CHECK-SPI-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/spi.swift" // CHECK-SPI-NEXT: } // CHECK-SPI-NEXT: ], // CHECK-SPI-NEXT: "classMethods": [] diff --git a/test/APIJSON/struct.swift b/test/APIJSON/struct.swift index ac7d27bcc18b9..dc613f1c2e258 100644 --- a/test/APIJSON/struct.swift +++ b/test/APIJSON/struct.swift @@ -2,7 +2,8 @@ // RUN: %empty-directory(%t) // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s +// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK,CHECK-EXTRACT +// RUN: %target-swift-frontend %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT // Struct has no objc data. @available(macOS 10.13, *) @@ -19,34 +20,39 @@ public struct TestStruct { // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule10TestStructV10testMethodyyF", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/struct.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.14" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule10TestStructVACycfC", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/struct.swift", // CHECK-NEXT: "linkage": "exported" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule10TestStructVMa", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/struct.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule10TestStructVMn", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/struct.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "name": "_$s8MyModule10TestStructVN", // CHECK-NEXT: "access": "public", -// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EXTRACT-NEXT: "file": "/@input/MyModule.swiftinterface", +// CHECK-EMIT-NEXT: "file": "SOURCE_DIR/test/APIJSON/struct.swift", // CHECK-NEXT: "linkage": "exported", // CHECK-NEXT: "introduced": "10.13" // CHECK-NEXT: } From 778532dbdf73c07867ae4ac53bb6fc5ab1934828 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Thu, 5 Oct 2023 11:33:14 -0700 Subject: [PATCH 3/3] TBDGen: Don't emit pretty-printed API descriptor JSON by default. Instead, use the `%validate-json` lit substitution to validate and format the API descriptor file before running it through FileCheck. This allows us to avoid needing to introduce a dedicated frontend option just to control whether the output of -emit-api-descriptor is pretty printed. --- lib/FrontendTool/FrontendTool.cpp | 8 +++----- test/APIJSON/apigen.swift | 3 ++- test/APIJSON/extension.swift | 3 ++- test/APIJSON/non-objc-class.swift | 3 ++- test/APIJSON/non-swift-api.swift | 3 ++- test/APIJSON/spi.swift | 3 ++- test/APIJSON/struct.swift | 3 ++- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 04c3a18ac3fe5..573b2573d677e 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -810,11 +810,10 @@ static bool writeTBDIfNeeded(CompilerInstance &Instance) { } static bool writeAPIDescriptor(ModuleDecl *M, StringRef OutputPath, - llvm::vfs::OutputBackend &Backend, - bool PrettyPrinted) { + llvm::vfs::OutputBackend &Backend) { return withOutputPath(M->getDiags(), Backend, OutputPath, [&](raw_ostream &OS) -> bool { - writeAPIJSONFile(M, OS, PrettyPrinted); + writeAPIJSONFile(M, OS, /*PrettyPrinted=*/false); return false; }); } @@ -834,9 +833,8 @@ static bool writeAPIDescriptorIfNeeded(CompilerInstance &Instance) { const std::string &APIDescriptorPath = Invocation.getAPIDescriptorPathForWholeModule(); - // FIXME: Need a frontend flag for pretty printing return writeAPIDescriptor(Instance.getMainModule(), APIDescriptorPath, - Instance.getOutputBackend(), true); + Instance.getOutputBackend()); } static bool performCompileStepsPostSILGen(CompilerInstance &Instance, diff --git a/test/APIJSON/apigen.swift b/test/APIJSON/apigen.swift index 6a9bee66d1e77..d053ef2c68b62 100644 --- a/test/APIJSON/apigen.swift +++ b/test/APIJSON/apigen.swift @@ -3,7 +3,8 @@ // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK,CHECK-EXTRACT -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json +// RUN: %validate-json %t/api.json | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT import Foundation diff --git a/test/APIJSON/extension.swift b/test/APIJSON/extension.swift index 4781b359ec301..9165d212c004a 100644 --- a/test/APIJSON/extension.swift +++ b/test/APIJSON/extension.swift @@ -3,7 +3,8 @@ // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK,CHECK-EXTRACT -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json +// RUN: %validate-json %t/api.json | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT import Foundation diff --git a/test/APIJSON/non-objc-class.swift b/test/APIJSON/non-objc-class.swift index fe7688bca5b5f..522dee7852f73 100644 --- a/test/APIJSON/non-objc-class.swift +++ b/test/APIJSON/non-objc-class.swift @@ -3,7 +3,8 @@ // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s -check-prefixes=CHECK,CHECK-EXTRACT -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json +// RUN: %validate-json %t/api.json | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT import Foundation diff --git a/test/APIJSON/non-swift-api.swift b/test/APIJSON/non-swift-api.swift index e186b991c0fa8..b2e0bc18dfb7a 100644 --- a/test/APIJSON/non-swift-api.swift +++ b/test/APIJSON/non-swift-api.swift @@ -5,7 +5,8 @@ // RUN: cp %S/Inputs/NativeDep.h %t/NativeDep.framework/Headers // RUN: %target-swift-frontend %s -parse-as-library -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5 -// RUN: %target-swift-frontend %s -parse-as-library -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s +// RUN: %target-swift-frontend %s -parse-as-library -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json +// RUN: %validate-json %t/api.json | %FileCheck %s /// Check that both swiftmodule and swiftinterface can be used as input. // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t/cache -F %t | %FileCheck %s diff --git a/test/APIJSON/spi.swift b/test/APIJSON/spi.swift index 48b9fb2655bb9..8e65881387a00 100644 --- a/test/APIJSON/spi.swift +++ b/test/APIJSON/spi.swift @@ -6,7 +6,8 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -parse-as-library -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK-SPI,CHECK-SPI-EXTRACT -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -parse-as-library -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK-SPI,CHECK-SPI-EMIT +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -parse-as-library -emit-module -emit-module-path %t/MyModule.swiftmodule -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json +// RUN: %validate-json %t/api.json | %FileCheck %s --check-prefixes=CHECK-SPI,CHECK-SPI-EMIT import Foundation diff --git a/test/APIJSON/struct.swift b/test/APIJSON/struct.swift index dc613f1c2e258..47c63a69cb1d1 100644 --- a/test/APIJSON/struct.swift +++ b/test/APIJSON/struct.swift @@ -3,7 +3,8 @@ // RUN: %empty-directory(%t/ModuleCache) // RUN: %target-swift-frontend %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 // RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s --check-prefixes=CHECK,CHECK-EXTRACT -// RUN: %target-swift-frontend %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path - | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT +// RUN: %target-swift-frontend %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5 -emit-api-descriptor-path %t/api.json +// RUN: %validate-json %t/api.json | %FileCheck %s --check-prefixes=CHECK,CHECK-EMIT // Struct has no objc data. @available(macOS 10.13, *)