From f377f5789806a60294877f8ce3a239676be4a1f0 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Fri, 29 Aug 2025 22:43:11 -0700 Subject: [PATCH 1/5] feat: swift metadata --- metadata-generator/README.md | 28 ++++ .../TestFixtures/SwiftDemo/.gitignore | 22 +++ .../TestFixtures/SwiftDemo/Package.swift | 11 ++ .../TestFixtures/SwiftDemo/README.md | 53 +++++++ .../SwiftDemo/Sources/SwiftDemo/Demo.swift | 16 +++ .../build-step-metadata-generator.py | 8 ++ metadata-generator/src/CMakeLists.txt | 8 ++ .../src/Swift/SymbolGraphParser.cpp | 136 ++++++++++++++++++ .../src/Swift/SymbolGraphParser.h | 25 ++++ .../src/TypeScript/SwiftDefinitionWriter.cpp | 55 +++++++ .../src/TypeScript/SwiftDefinitionWriter.h | 38 +++++ metadata-generator/src/main.cpp | 118 +++++++++------ 12 files changed, 477 insertions(+), 41 deletions(-) create mode 100644 metadata-generator/TestFixtures/SwiftDemo/.gitignore create mode 100644 metadata-generator/TestFixtures/SwiftDemo/Package.swift create mode 100644 metadata-generator/TestFixtures/SwiftDemo/README.md create mode 100644 metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Demo.swift create mode 100644 metadata-generator/src/Swift/SymbolGraphParser.cpp create mode 100644 metadata-generator/src/Swift/SymbolGraphParser.h create mode 100644 metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp create mode 100644 metadata-generator/src/TypeScript/SwiftDefinitionWriter.h diff --git a/metadata-generator/README.md b/metadata-generator/README.md index 899608a63..fcc44d443 100644 --- a/metadata-generator/README.md +++ b/metadata-generator/README.md @@ -46,3 +46,31 @@ Example command line arguments: ``` For a better way of generating these arguments, just run the TestRunner scheme on the v8ios-runtime project and get the arguments from the log. + +## Swift (Symbol Graph) support + +You can generate TypeScript from Swift modules by pointing the generator to a directory of `.symbolgraph` files. + +1. Produce symbol graphs for your Swift module (Swift 5.9+): + +``` +swift build +swift symbolgraph-extract --module-name YourModule \ + --minimum-access-level public \ + --output-dir .symbolgraph +``` + +2. Run the generator with the new flags: + +``` +./objc-metadata-generator \ + -output-typescript \ + --swift-symbolgraph-dir /.symbolgraph \ + --skip-objc +``` + +Environment variables (if using build-step script): +- `NS_SWIFT_SYMBOLGRAPH_DIR` (or `TNS_SWIFT_SYMBOLGRAPH_DIR`) – path to symbol graph directory +- `NS_SKIP_OBJC_METADATA` (or `TNS_SKIP_OBJC_METADATA`) – set to `1` to skip Objective-C phase + +A tiny sample package is in `TestFixtures/SwiftDemo`. See its README for quick steps. diff --git a/metadata-generator/TestFixtures/SwiftDemo/.gitignore b/metadata-generator/TestFixtures/SwiftDemo/.gitignore new file mode 100644 index 000000000..45b95a52f --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/.gitignore @@ -0,0 +1,22 @@ +# SwiftPM build artifacts +.build/ +.swiftpm/ + +# Generated symbol graphs +.symbolgraph/ +*.symbolgraph +*.symbols.json + +# Swift package resolution (optional to commit; ignore for test fixture) +Package.resolved + +# macOS noise +.DS_Store + +# Editor/IDE +.vscode/ +.idea/ + +# Deprecated Xcode project generation artifacts +*.xcodeproj/ +*.xcworkspace/ diff --git a/metadata-generator/TestFixtures/SwiftDemo/Package.swift b/metadata-generator/TestFixtures/SwiftDemo/Package.swift new file mode 100644 index 000000000..214748ca7 --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "SwiftDemo", + platforms: [ .iOS(.v15) ], + products: [ .library(name: "SwiftDemo", targets: ["SwiftDemo"]) ], + targets: [ + .target(name: "SwiftDemo", path: "Sources") + ] +) diff --git a/metadata-generator/TestFixtures/SwiftDemo/README.md b/metadata-generator/TestFixtures/SwiftDemo/README.md new file mode 100644 index 000000000..499f80944 --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/README.md @@ -0,0 +1,53 @@ +This is a tiny Swift package used to generate a Symbol Graph for testing. + +Generate symbol graph (optional): + +``` +cd metadata-generator/TestFixtures/SwiftDemo +# Swift 5.9+ required +swift build +swift symbolgraph-extract --module-name SwiftDemo --minimum-access-level public --output-dir .symbolgraph +``` + +Then run the metadata generator: + +``` +# Add your normal args plus: +# --output-typescript +# --swift-symbolgraph-dir /TestFixtures/SwiftDemo/.symbolgraph +# The ObjC path can still run as usual. +``` + +Example: +``` +cd ../../.. +./build/objc-metadata-generator \ + -output-typescript /tmp/ts-out \ + --swift-symbolgraph-dir metadata-generator/TestFixtures/SwiftDemo/.symbolgraph \ + --skip-objc +``` + +Result: +- `/tmp/ts-out/swift!SwiftDemo.d.ts` (skeleton content, e.g., declare class Demo, interface Greeter, struct Point, enum Flavor) + +If you prefer running via the build-step script, set: + +``` +NS_SWIFT_SYMBOLGRAPH_DIR=/absolute/path/to/.symbolgraph +NS_SKIP_OBJC_METADATA=1 +``` + +Done: + +- CMake wired to compile new sources: + - Added Swift/SymbolGraphParser.{h,cpp} and TypeScript/SwiftDefinitionWriter.{h,cpp} to CMakeLists.txt. +- CLI integration: + -In main.cpp: added --swift-symbolgraph-dir and --skip-objc, scan symbolgraph dir, parse per module, emit swift!.d.ts. Obj‑C phase is skipped when --skip-objc is set. +- Swift parser (bootstrap): + - Swift/SymbolGraphParser: scans a directory for .symbolgraph/.symbols.json, groups by module, and creates placeholder Meta entries (class/struct/enum/protocol) to prove the pipeline. +- Swift TS writer (bootstrap): + - TypeScript/SwiftDefinitionWriter: writes minimal TS declarations from the Swift Meta set. +- Build step env passthrough: + - build-step-metadata-generator.py: respects NS_SWIFT_SYMBOLGRAPH_DIR/TNS_SWIFT_SYMBOLGRAPH_DIR and NS_SKIP_OBJC_METADATA/TNS_SKIP_OBJC_METADATA. +- Test fixture: + - TestFixtures/SwiftDemo SwiftPM package with Demo.swift and README showing how to emit symbol graphs. \ No newline at end of file diff --git a/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Demo.swift b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Demo.swift new file mode 100644 index 000000000..bb55705a4 --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Demo.swift @@ -0,0 +1,16 @@ +public protocol Greeter { + func greet(name: String) -> String +} + +public class Demo: Greeter { + public init() {} + public func greet(name: String) -> String { "Hello, \(name)" } +} + +public struct Point { + public var x: Double + public var y: Double + public init(x: Double, y: Double) { self.x = x; self.y = y } +} + +public enum Flavor: Int { case vanilla = 0, chocolate = 1 } diff --git a/metadata-generator/build-step-metadata-generator.py b/metadata-generator/build-step-metadata-generator.py index 1acd946c9..cb1f0491f 100755 --- a/metadata-generator/build-step-metadata-generator.py +++ b/metadata-generator/build-step-metadata-generator.py @@ -114,6 +114,8 @@ def map_and_list(func, iterable): .format(docset_platform)) yaml_output_folder = env_or_none("NS_DEBUG_METADATA_PATH") or env_or_none("TNS_DEBUG_METADATA_PATH") strict_includes = env_or_none("NS_DEBUG_METADATA_STRICT_INCLUDES") or env_or_none("TNS_DEBUG_METADATA_STRICT_INCLUDES") +swift_symbolgraph_dir = env_or_none("NS_SWIFT_SYMBOLGRAPH_DIR") or env_or_none("TNS_SWIFT_SYMBOLGRAPH_DIR") +skip_objc = env_bool("NS_SKIP_OBJC_METADATA") or env_bool("TNS_SKIP_OBJC_METADATA") def save_stream_to_file(filename, stream): @@ -133,6 +135,12 @@ def generate_metadata(arch): if strict_includes is not None: generator_call.extend(["-strict-includes={}".format(strict_includes)]) + # Swift-only mode or Swift supplement + if swift_symbolgraph_dir is not None and len(swift_symbolgraph_dir) > 0: + generator_call.extend(["--swift-symbolgraph-dir", swift_symbolgraph_dir]) + if skip_objc: + generator_call.extend(["--skip-objc"]) + # optionally add typescript output folder if typescript_output_folder is not None: current_typescript_output_folder = os.path.join(typescript_output_folder, arch) diff --git a/metadata-generator/src/CMakeLists.txt b/metadata-generator/src/CMakeLists.txt index 037abdc98..5942ac24f 100644 --- a/metadata-generator/src/CMakeLists.txt +++ b/metadata-generator/src/CMakeLists.txt @@ -35,6 +35,10 @@ set(GENERATOR_HEADERS Utils/StringUtils.h Yaml/MetaYamlTraits.h Yaml/YamlSerializer.h + + # Swift support + Swift/SymbolGraphParser.h + TypeScript/SwiftDefinitionWriter.h ) set(GENERATOR_SOURCES @@ -63,6 +67,10 @@ set(GENERATOR_SOURCES TypeScript/DocSetManager.cpp Utils/fileStream.cpp Utils/memoryStream.cpp + + # Swift support + Swift/SymbolGraphParser.cpp + TypeScript/SwiftDefinitionWriter.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR}) diff --git a/metadata-generator/src/Swift/SymbolGraphParser.cpp b/metadata-generator/src/Swift/SymbolGraphParser.cpp new file mode 100644 index 000000000..39f36f2df --- /dev/null +++ b/metadata-generator/src/Swift/SymbolGraphParser.cpp @@ -0,0 +1,136 @@ +#include "SymbolGraphParser.h" + +#include +#include +#include +#include + +#include "Meta/MetaEntities.h" +#include "Meta/TypeFactory.h" + +#include +#include +namespace fs = llvm::sys::fs; +namespace path = llvm::sys::path; + +namespace Swift { + +static bool hasSymbolGraphExt(llvm::StringRef filePath) { + auto ext = path::extension(filePath); + return ext == ".symbolgraph" || ext == ".json" || ext == ".symbols"; // allow *.symbols.json +} + +ModuleGraphs SymbolGraphParser::scanDirectory(const std::string& dirPath) { + ModuleGraphs result; + std::error_code ec; + if (!fs::exists(dirPath, ec)) { + return result; + } + + std::regex moduleHint("([A-Za-z0-9_]+)\\.symbols?\\.json$|([A-Za-z0-9_]+)\\.symbolgraph$"); + + for (fs::recursive_directory_iterator it(dirPath, ec), end; it != end && !ec; it.increment(ec)) { + if (ec) break; + if (it->type() != fs::file_type::regular_file) continue; + auto p = it->path(); + if (!hasSymbolGraphExt(p)) continue; + + std::smatch m; + std::string filename = std::string(path::filename(p)); + std::string module; + if (std::regex_search(filename, m, moduleHint)) { + if (m[1].matched) module = m[1].str(); + else if (m[2].matched) module = m[2].str(); + } + if (module.empty()) { + module = std::string(path::filename(path::parent_path(p))); + } + result.filesByModule[module].push_back(std::string(p)); + } + return result; +} + +// Extremely lightweight JSON helpers (only what we need for skeleton) +static std::string findString(const std::string& json, const std::string& key) { + // naive: "key":"value" + auto k = std::string("\"") + key + "\""; + auto pos = json.find(k); + if (pos == std::string::npos) return ""; + pos = json.find(':', pos); + if (pos == std::string::npos) return ""; + pos = json.find('"', pos); + if (pos == std::string::npos) return ""; + auto end = json.find('"', pos + 1); + if (end == std::string::npos) return ""; + return json.substr(pos + 1, end - pos - 1); +} + +static bool contains(const std::string& hay, const std::string& needle) { + return hay.find(needle) != std::string::npos; +} + +std::vector SymbolGraphParser::parseModule(const std::string& moduleName, + const std::vector& graphFiles) { + using namespace Meta; + std::vector metas; + metas.reserve(128); + + // For the skeleton: detect a few simple symbol kinds and emit placeholder metas. + for (const auto& f : graphFiles) { + std::ifstream in(f); + if (!in.good()) continue; + std::stringstream buffer; buffer << in.rdbuf(); + auto json = buffer.str(); + + // naive scan for "symbol" entries and pick a few kinds + // e.g., "kind": { "identifier": "swift.class" }, name, module, etc. + // We'll create InterfaceMeta for class, StructMeta for struct, EnumMeta for enum. + + // This is a placeholder approach; a complete parser should iterate the JSON arrays. + // We’ll just search by snippets to bootstrap. + if (contains(json, "swift.class")) { + auto name = findString(json, "title"); + auto* iface = new InterfaceMeta(); + iface->name = name.empty() ? "SwiftClass" : name; + iface->jsName = iface->name; + metas.push_back(iface); + } + if (contains(json, "swift.struct")) { + auto name = findString(json, "title"); + auto* st = new StructMeta(); + st->name = name.empty() ? "SwiftStruct" : name; + st->jsName = st->name; + metas.push_back(st); + } + if (contains(json, "swift.enum")) { + auto name = findString(json, "title"); + auto* en = new EnumMeta(); + en->name = name.empty() ? "SwiftEnum" : name; + en->jsName = en->name; + metas.push_back(en); + } + if (contains(json, "swift.protocol")) { + auto name = findString(json, "title"); + auto* pr = new ProtocolMeta(); + pr->name = name.empty() ? "SwiftProtocol" : name; + pr->jsName = pr->name; + metas.push_back(pr); + } + } + + // de-dup very naively by jsName + std::unordered_map byName; + std::vector unique; + for (auto* m : metas) { + if (!m) continue; + if (!byName.count(m->jsName)) { + byName[m->jsName] = m; + unique.push_back(m); + } else { + delete m; // drop duplicates in bootstrap + } + } + return unique; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SymbolGraphParser.h b/metadata-generator/src/Swift/SymbolGraphParser.h new file mode 100644 index 000000000..4ccd53f35 --- /dev/null +++ b/metadata-generator/src/Swift/SymbolGraphParser.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +namespace Meta { class Meta; } + +namespace Swift { +struct ModuleGraphs { + // Module name -> list of file paths (*.symbolgraph and/or *.symbols.json) + std::unordered_map> filesByModule; +}; + +// Minimal Swift symbolgraph -> Meta bridge +class SymbolGraphParser { +public: + // Scan a directory for *.symbolgraph or *.symbols.json and group by module + static ModuleGraphs scanDirectory(const std::string& dirPath); + + // Parse all symbol graph files for a module into Meta objects + static std::vector parseModule(const std::string& moduleName, + const std::vector& graphFiles); +}; +} diff --git a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp new file mode 100644 index 000000000..c2f680bb1 --- /dev/null +++ b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp @@ -0,0 +1,55 @@ +#include "SwiftDefinitionWriter.h" + +#include "Meta/MetaEntities.h" + +namespace TypeScript { +using namespace Meta; + +std::string SwiftDefinitionWriter::write() { + // Header + _buffer << "// Generated from Swift Symbol Graphs\n"; + _buffer << "// Module: " << _module.first << "\n\n"; + + for (auto *m : _module.second) { + if (m) m->visit(this); + } + + return _buffer.str(); +} + +void SwiftDefinitionWriter::visit(InterfaceMeta* meta) { + _buffer << "declare class " << meta->jsName << " { }\n"; +} + +void SwiftDefinitionWriter::visit(ProtocolMeta* meta) { + _buffer << "interface " << meta->jsName << " { }\n"; +} + +void SwiftDefinitionWriter::visit(CategoryMeta* /*meta*/) {} + +void SwiftDefinitionWriter::visit(FunctionMeta* meta) { + _buffer << "declare function " << meta->jsName << "(...args: any[]): any;\n"; +} + +void SwiftDefinitionWriter::visit(StructMeta* meta) { + _buffer << "interface " << meta->jsName << " { }\n"; + _buffer << "declare var " << meta->jsName << ": interop.StructType<" << meta->jsName << ">;\n"; +} + +void SwiftDefinitionWriter::visit(UnionMeta* meta) { + _buffer << "interface " << meta->jsName << " { }\n"; +} + +void SwiftDefinitionWriter::visit(EnumMeta* meta) { + _buffer << "declare const enum " << meta->jsName << " { }\n"; +} + +void SwiftDefinitionWriter::visit(VarMeta* meta) { + _buffer << "declare var " << meta->jsName << ": any;\n"; +} + +void SwiftDefinitionWriter::visit(MethodMeta* /*meta*/) {} +void SwiftDefinitionWriter::visit(PropertyMeta* /*meta*/) {} +void SwiftDefinitionWriter::visit(EnumConstantMeta* /*meta*/) {} + +} // namespace TypeScript diff --git a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h new file mode 100644 index 000000000..aa7679418 --- /dev/null +++ b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h @@ -0,0 +1,38 @@ +#pragma once + +#include "DocSetManager.h" +#include "Meta/MetaEntities.h" +#include +#include +#include +#include +#include + +namespace TypeScript { +class SwiftDefinitionWriter : Meta::MetaVisitor { +public: + SwiftDefinitionWriter(std::pair> &module, + std::string docSetPath) + : _module(module), _docSet(docSetPath) {} + + std::string write(); + + // MetaVisitor + void visit(Meta::InterfaceMeta* meta) override; + void visit(Meta::ProtocolMeta* meta) override; + void visit(Meta::CategoryMeta* meta) override; + void visit(Meta::FunctionMeta* meta) override; + void visit(Meta::StructMeta* meta) override; + void visit(Meta::UnionMeta* meta) override; + void visit(Meta::EnumMeta* meta) override; + void visit(Meta::VarMeta* meta) override; + void visit(Meta::MethodMeta* meta) override; + void visit(Meta::PropertyMeta* meta) override; + void visit(Meta::EnumConstantMeta* meta) override; + +private: + std::pair> &_module; // moduleName, metas + DocSetManager _docSet; + std::ostringstream _buffer; +}; +} diff --git a/metadata-generator/src/main.cpp b/metadata-generator/src/main.cpp index f4b7b8aee..6b9f45854 100644 --- a/metadata-generator/src/main.cpp +++ b/metadata-generator/src/main.cpp @@ -10,13 +10,17 @@ #include "TypeScript/DefinitionWriter.h" #include "TypeScript/DocSetManager.h" #include "Yaml/YamlSerializer.h" +#include "Swift/SymbolGraphParser.h" +#include "TypeScript/SwiftDefinitionWriter.h" #include #include #include #include +#include #include #include #include +#include // Command line parameters llvm::cl::opt cla_verbose("verbose", llvm::cl::desc("Set verbose output mode"), llvm::cl::value_desc("bool")); @@ -34,6 +38,10 @@ llvm::cl::opt cla_applyManualDtsChanges("apply-manual-dts-changes", llvm llvm::cl::opt cla_clangArgumentsDelimiter(llvm::cl::Positional, llvm::cl::desc("Xclang"), llvm::cl::init("-")); llvm::cl::list cla_clangArguments(llvm::cl::ConsumeAfter, llvm::cl::desc("...")); +// Swift support +llvm::cl::opt cla_swiftSymbolGraphDir("swift-symbolgraph-dir", llvm::cl::desc("Directory containing Swift .symbolgraph files to import"), llvm::cl::value_desc("")); +llvm::cl::opt cla_skipObjC("skip-objc", llvm::cl::desc("Skip Objective-C parsing and only run Swift symbolgraph import"), llvm::cl::init(false)); + class MetaGenerationConsumer : public clang::ASTConsumer { public: explicit MetaGenerationConsumer(clang::SourceManager& sourceManager, clang::HeaderSearch& headerSearch, Meta::ModulesBlacklist& modulesBlacklist) @@ -102,7 +110,7 @@ class MetaGenerationConsumer : public clang::ASTConsumer { file.save(cla_outputBinFile); } - // Generate TypeScript definitions + // Generate TypeScript definitions (Objective-C) if (!cla_outputDtsFolder.empty()) { llvm::sys::fs::create_directories(cla_outputDtsFolder); std::string docSetPath = cla_docSetFile.empty() ? "" : cla_docSetFile.getValue(); @@ -183,54 +191,82 @@ int main(int argc, const char** argv) TypeScript::DefinitionWriter::applyManualChanges = cla_applyManualDtsChanges; - std::vector clangArgs{ - "-v", - "-x", "objective-c", - "-fno-objc-arc", "-fmodule-maps", "-ferror-limit=0", - "-Wno-unknown-pragmas", "-Wno-ignored-attributes", "-Wno-nullability-completeness", "-Wno-expansion-to-defined", - "-D__NATIVESCRIPT_METADATA_GENERATOR=1" - }; - - // merge with hardcoded clang arguments - clangArgs.insert(clangArgs.end(), cla_clangArguments.begin(), cla_clangArguments.end()); - - // Log Clang Arguments - std::cout << "Clang Arguments: \n"; - for (const std::string& arg : clangArgs) { - std::cout << "\"" << arg << "\"," - << " "; - } - std::cout << std::endl; + if (!cla_skipObjC) { + std::vector clangArgs{ + "-v", + "-x", "objective-c", + "-fno-objc-arc", "-fmodule-maps", "-ferror-limit=0", + "-Wno-unknown-pragmas", "-Wno-ignored-attributes", "-Wno-nullability-completeness", "-Wno-expansion-to-defined", + "-D__NATIVESCRIPT_METADATA_GENERATOR=1" + }; + + // merge with hardcoded clang arguments + clangArgs.insert(clangArgs.end(), cla_clangArguments.begin(), cla_clangArguments.end()); + + // Log Clang Arguments + std::cout << "Clang Arguments: \n"; + for (const std::string& arg : clangArgs) { + std::cout << "\"" << arg << "\"," << " "; + } + std::cout << std::endl; - std::string isysroot; - std::vector::const_iterator it = std::find(clangArgs.begin(), clangArgs.end(), "-isysroot"); - if (it != clangArgs.end() && ++it != clangArgs.end()) { - isysroot = *it; - } + std::string isysroot; + std::vector::const_iterator it = std::find(clangArgs.begin(), clangArgs.end(), "-isysroot"); + if (it != clangArgs.end() && ++it != clangArgs.end()) { + isysroot = *it; + } - std::vector includePaths; - std::string umbrellaContent = CreateUmbrellaHeader(clangArgs, includePaths); + std::vector includePaths; + std::string umbrellaContent = CreateUmbrellaHeader(clangArgs, includePaths); - if (!cla_inputUmbrellaHeaderFile.empty()) { - std::ifstream fs(cla_inputUmbrellaHeaderFile); - umbrellaContent = std::string((std::istreambuf_iterator(fs)), - std::istreambuf_iterator()); + if (!cla_inputUmbrellaHeaderFile.empty()) { + std::ifstream fs(cla_inputUmbrellaHeaderFile); + umbrellaContent = std::string((std::istreambuf_iterator(fs)), std::istreambuf_iterator()); + } + + clangArgs.insert(clangArgs.end(), includePaths.begin(), includePaths.end()); + + // Save the umbrella file + if (!cla_outputUmbrellaHeaderFile.empty()) { + std::error_code errorCode; + llvm::raw_fd_ostream umbrellaFileStream(cla_outputUmbrellaHeaderFile, errorCode, llvm::sys::fs::OpenFlags::OF_None); + if (!errorCode) { + umbrellaFileStream << umbrellaContent; + umbrellaFileStream.close(); + } + } + // generate metadata for the intermediate sdk header + Meta::ModulesBlacklist modulesBlacklist(cla_whiteListModuleRegexesFile, cla_blackListModuleRegexesFile); + clang::tooling::runToolOnCodeWithArgs(std::unique_ptr(new MetaGenerationFrontendAction(/*r*/modulesBlacklist)), umbrellaContent, clangArgs, "umbrella.h", "objc-metadata-generator"); } - clangArgs.insert(clangArgs.end(), includePaths.begin(), includePaths.end()); + // Swift: read symbol graphs and emit TS + if (!cla_outputDtsFolder.empty() && !cla_swiftSymbolGraphDir.empty()) { + auto graphs = Swift::SymbolGraphParser::scanDirectory(cla_swiftSymbolGraphDir); + llvm::sys::fs::create_directories(cla_outputDtsFolder); + std::string docSetPath = cla_docSetFile.empty() ? "" : cla_docSetFile.getValue(); + for (auto &entry : graphs.filesByModule) { + const auto &moduleName = entry.first; + const auto &files = entry.second; + auto metas = Swift::SymbolGraphParser::parseModule(moduleName, files); + std::pair> swiftModule(moduleName, metas); + + TypeScript::SwiftDefinitionWriter swiftWriter(swiftModule, docSetPath); + llvm::SmallString<128> path; + llvm::sys::path::append(path, cla_outputDtsFolder, "swift!" + moduleName + ".d.ts"); + std::error_code error; + llvm::raw_fd_ostream file(path.str(), error, llvm::sys::fs::OF_Text); + if (error) { + std::cout << error.message(); + } else { + file << swiftWriter.write(); + file.close(); + } - // Save the umbrella file - if (!cla_outputUmbrellaHeaderFile.empty()) { - std::error_code errorCode; - llvm::raw_fd_ostream umbrellaFileStream(cla_outputUmbrellaHeaderFile, errorCode, llvm::sys::fs::OpenFlags::OF_None); - if (!errorCode) { - umbrellaFileStream << umbrellaContent; - umbrellaFileStream.close(); + // cleanup allocated metas (bootstrap only; later we will manage via factories) + for (auto *m : metas) delete m; } } - // generate metadata for the intermediate sdk header - Meta::ModulesBlacklist modulesBlacklist(cla_whiteListModuleRegexesFile, cla_blackListModuleRegexesFile); - clang::tooling::runToolOnCodeWithArgs(std::unique_ptr(new MetaGenerationFrontendAction(/*r*/modulesBlacklist)), umbrellaContent, clangArgs, "umbrella.h", "objc-metadata-generator"); std::clock_t end = clock(); double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; From 02a340fdf46a58bed7e71c4ddf244816165c4c00 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 20 Oct 2026 10:32:25 -0700 Subject: [PATCH 2/5] feat(metadata-generator): structural Swift symbol graph loader and IR Replace the substring-matching SymbolGraphParser with SymbolGraphLoader, which reads symbol graphs with llvm::json into a Swift-specific IR (src/Swift/SwiftIR.h) instead of the Objective-C Meta model. The IR records every public declaration with its USR, kind, access, parameters (labels, internal names, inout/ownership, type attributes, defaults), effects, settability, failable initializers, generics, availability, extension info and actor attributes, and resolves memberOf/requirementOf/conformsTo/inheritsFrom/overrides relationships, including members of types declared in other modules. Parameters are parsed from declarationFragments because functionSignature reports the internal name instead of the argument label for unlabeled parameters and drops @autoclosure and default values; parsed labels are cross-checked against the symbol name. Load problems surface as diagnostics with stable codes, and errors make the generator exit non-zero. - swift!.d.ts is explicitly type-only: top-level type names, no members, until Swift members are callable. - --swift-ir-output writes a deterministic JSON dump of the IR. - swift-symbolgraph-tests (CTest) covers the loader against checked-in SwiftDemo graphs, with IR and .d.ts snapshots. - SwiftDemo gains declarations for every shape the loader models; generate-symbolgraphs.sh reproduces the checked-in graphs. Objective-C output is unchanged: metadata.bin and all .d.ts files for the iOS simulator SDK are byte-identical to origin/main's generator. --- metadata-generator/CMakeLists.txt | 3 + metadata-generator/README.md | 50 +- .../TestFixtures/SwiftDemo/.gitignore | 3 +- .../TestFixtures/SwiftDemo/README.md | 61 +- .../Sources/SwiftDemo/Extensions.swift | 29 + .../SwiftDemo/Sources/SwiftDemo/Shapes.swift | 137 + .../SwiftDemo/generate-symbolgraphs.sh | 32 + .../symbolgraphs/SwiftDemo.symbols.json | 1 + .../symbolgraphs/SwiftDemo@Swift.symbols.json | 1 + metadata-generator/src/CMakeLists.txt | 6 +- metadata-generator/src/Swift/SwiftIR.cpp | 341 +++ metadata-generator/src/Swift/SwiftIR.h | 264 ++ .../src/Swift/SymbolGraphLoader.cpp | 1070 +++++++ .../src/Swift/SymbolGraphLoader.h | 47 + .../src/Swift/SymbolGraphParser.cpp | 136 - .../src/Swift/SymbolGraphParser.h | 25 - .../src/TypeScript/SwiftDefinitionWriter.cpp | 64 +- .../src/TypeScript/SwiftDefinitionWriter.h | 43 +- metadata-generator/src/main.cpp | 102 +- metadata-generator/tests/CMakeLists.txt | 17 + .../tests/swift/SymbolGraphLoaderTests.cpp | 628 ++++ metadata-generator/tests/swift/TestHarness.h | 94 + .../tests/swift/snapshots/SwiftDemo.ir.json | 2622 +++++++++++++++++ .../swift/snapshots/swift!SwiftDemo.d.ts | 16 + 24 files changed, 5456 insertions(+), 336 deletions(-) create mode 100644 metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Extensions.swift create mode 100644 metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift create mode 100755 metadata-generator/TestFixtures/SwiftDemo/generate-symbolgraphs.sh create mode 100644 metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json create mode 100644 metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo@Swift.symbols.json create mode 100644 metadata-generator/src/Swift/SwiftIR.cpp create mode 100644 metadata-generator/src/Swift/SwiftIR.h create mode 100644 metadata-generator/src/Swift/SymbolGraphLoader.cpp create mode 100644 metadata-generator/src/Swift/SymbolGraphLoader.h delete mode 100644 metadata-generator/src/Swift/SymbolGraphParser.cpp delete mode 100644 metadata-generator/src/Swift/SymbolGraphParser.h create mode 100644 metadata-generator/tests/CMakeLists.txt create mode 100644 metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp create mode 100644 metadata-generator/tests/swift/TestHarness.h create mode 100644 metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json create mode 100644 metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts diff --git a/metadata-generator/CMakeLists.txt b/metadata-generator/CMakeLists.txt index 4ae9950df..bc57c05a8 100644 --- a/metadata-generator/CMakeLists.txt +++ b/metadata-generator/CMakeLists.txt @@ -69,5 +69,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) add_subdirectory(src) + +enable_testing() +add_subdirectory(tests) # copy build-step-metadata-generator.py to the bin folder configure_file(build-step-metadata-generator.py ${CMAKE_CURRENT_BINARY_DIR}/bin/build-step-metadata-generator.py COPYONLY) diff --git a/metadata-generator/README.md b/metadata-generator/README.md index fcc44d443..122467be6 100644 --- a/metadata-generator/README.md +++ b/metadata-generator/README.md @@ -49,28 +49,50 @@ For a better way of generating these arguments, just run the TestRunner scheme o ## Swift (Symbol Graph) support -You can generate TypeScript from Swift modules by pointing the generator to a directory of `.symbolgraph` files. - -1. Produce symbol graphs for your Swift module (Swift 5.9+): - -``` -swift build -swift symbolgraph-extract --module-name YourModule \ - --minimum-access-level public \ - --output-dir .symbolgraph -``` - -2. Run the generator with the new flags: +The generator can import Swift modules from symbol graphs (`*.symbols.json`, as +written by `swiftc -emit-symbol-graph` or `swift symbolgraph-extract`). Graphs +are loaded structurally into a Swift-specific IR (`src/Swift/SwiftIR.h`): every +public declaration with its precise USR, kind, access level, parameters and +labels, effects (`async`/`throws`), settability, generics, availability, +extension info, and resolved relationships (members, conformances, superclass, +overrides, protocol requirements). Malformed or unexpected input is reported as +diagnostics with stable codes (`invalid-json`, `unsupported-format-version`, +`duplicate-symbol`, `parameter-label-mismatch`, ...); errors make the generator +exit non-zero. + +Swift declarations are not callable from JavaScript yet, so the emitted +`swift!.d.ts` is type-only: it names the module's top-level types and +declares no members. ``` ./objc-metadata-generator \ -output-typescript \ - --swift-symbolgraph-dir /.symbolgraph \ + --swift-symbolgraph-dir /symbolgraphs \ + --swift-ir-output \ --skip-objc ``` +- `--swift-symbolgraph-dir` – directory searched recursively for symbol graphs +- `--swift-ir-output` – optional; writes `.swift-ir.json`, a deterministic dump of the IR +- `--skip-objc` – skip the Objective-C phase + Environment variables (if using build-step script): - `NS_SWIFT_SYMBOLGRAPH_DIR` (or `TNS_SWIFT_SYMBOLGRAPH_DIR`) – path to symbol graph directory - `NS_SKIP_OBJC_METADATA` (or `TNS_SKIP_OBJC_METADATA`) – set to `1` to skip Objective-C phase -A tiny sample package is in `TestFixtures/SwiftDemo`. See its README for quick steps. +### Tests + +`swift-symbolgraph-tests` is built alongside the generator and runs against the +checked-in graphs in `TestFixtures/SwiftDemo/symbolgraphs`, so it needs no Swift +toolchain: + +``` +cmake --build build --target swift-symbolgraph-tests +./build/bin/swift-symbolgraph-tests # or: (cd build && ctest) +./build/bin/swift-symbolgraph-tests Snapshot # run tests whose name contains "Snapshot" +``` + +`IRSnapshot` and `TypeScriptSnapshot` compare against +`tests/swift/snapshots/`. After an intended output change, regenerate them with +`NS_UPDATE_SNAPSHOTS=1 ./build/bin/swift-symbolgraph-tests Snapshot` and review +the diff. diff --git a/metadata-generator/TestFixtures/SwiftDemo/.gitignore b/metadata-generator/TestFixtures/SwiftDemo/.gitignore index 45b95a52f..14dfef462 100644 --- a/metadata-generator/TestFixtures/SwiftDemo/.gitignore +++ b/metadata-generator/TestFixtures/SwiftDemo/.gitignore @@ -2,10 +2,11 @@ .build/ .swiftpm/ -# Generated symbol graphs +# Generated symbol graphs, except the checked-in corpus the loader tests read .symbolgraph/ *.symbolgraph *.symbols.json +!symbolgraphs/*.symbols.json # Swift package resolution (optional to commit; ignore for test fixture) Package.resolved diff --git a/metadata-generator/TestFixtures/SwiftDemo/README.md b/metadata-generator/TestFixtures/SwiftDemo/README.md index 499f80944..81e822bd1 100644 --- a/metadata-generator/TestFixtures/SwiftDemo/README.md +++ b/metadata-generator/TestFixtures/SwiftDemo/README.md @@ -1,53 +1,20 @@ -This is a tiny Swift package used to generate a Symbol Graph for testing. +# SwiftDemo fixture -Generate symbol graph (optional): +A Swift package whose declarations cover the shapes the Swift symbol graph +loader must model: classes, structs, enums with raw and associated values, +protocols, actors, `@MainActor` types, nested types, overloads, operators, +subscripts, failable initializers, `async`/`throws`, `inout` and escaping +closure parameters, generics, availability, and extensions of both module and +standard library types. -``` -cd metadata-generator/TestFixtures/SwiftDemo -# Swift 5.9+ required -swift build -swift symbolgraph-extract --module-name SwiftDemo --minimum-access-level public --output-dir .symbolgraph -``` - -Then run the metadata generator: - -``` -# Add your normal args plus: -# --output-typescript -# --swift-symbolgraph-dir /TestFixtures/SwiftDemo/.symbolgraph -# The ObjC path can still run as usual. -``` +`symbolgraphs/` holds the graphs generated from `Sources/`. The loader tests +read these checked-in files, so they run without a Swift toolchain. After +changing `Sources/`, regenerate the graphs and then the test snapshots: -Example: ``` -cd ../../.. -./build/objc-metadata-generator \ - -output-typescript /tmp/ts-out \ - --swift-symbolgraph-dir metadata-generator/TestFixtures/SwiftDemo/.symbolgraph \ - --skip-objc +./generate-symbolgraphs.sh +NS_UPDATE_SNAPSHOTS=1 ../../build/bin/swift-symbolgraph-tests Snapshot ``` -Result: -- `/tmp/ts-out/swift!SwiftDemo.d.ts` (skeleton content, e.g., declare class Demo, interface Greeter, struct Point, enum Flavor) - -If you prefer running via the build-step script, set: - -``` -NS_SWIFT_SYMBOLGRAPH_DIR=/absolute/path/to/.symbolgraph -NS_SKIP_OBJC_METADATA=1 -``` - -Done: - -- CMake wired to compile new sources: - - Added Swift/SymbolGraphParser.{h,cpp} and TypeScript/SwiftDefinitionWriter.{h,cpp} to CMakeLists.txt. -- CLI integration: - -In main.cpp: added --swift-symbolgraph-dir and --skip-objc, scan symbolgraph dir, parse per module, emit swift!.d.ts. Obj‑C phase is skipped when --skip-objc is set. -- Swift parser (bootstrap): - - Swift/SymbolGraphParser: scans a directory for .symbolgraph/.symbols.json, groups by module, and creates placeholder Meta entries (class/struct/enum/protocol) to prove the pipeline. -- Swift TS writer (bootstrap): - - TypeScript/SwiftDefinitionWriter: writes minimal TS declarations from the Swift Meta set. -- Build step env passthrough: - - build-step-metadata-generator.py: respects NS_SWIFT_SYMBOLGRAPH_DIR/TNS_SWIFT_SYMBOLGRAPH_DIR and NS_SKIP_OBJC_METADATA/TNS_SKIP_OBJC_METADATA. -- Test fixture: - - TestFixtures/SwiftDemo SwiftPM package with Demo.swift and README showing how to emit symbol graphs. \ No newline at end of file +Review the resulting snapshot diff before committing it; it is the record of +what the loader extracts. diff --git a/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Extensions.swift b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Extensions.swift new file mode 100644 index 000000000..6bbc747b1 --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Extensions.swift @@ -0,0 +1,29 @@ +extension Demo { + public func greet(name: String, times: Int) -> String { + String(repeating: greet(name: name), count: times) + } + + public static var version: String { "1.0" } +} + +extension Point: CustomStringConvertible { + public var description: String { "(\(x), \(y))" } + public var length: Double { (x * x + y * y).squareRoot() } +} + +extension Flavor: CustomStringConvertible { + public var description: String { self == .vanilla ? "vanilla" : "chocolate" } +} + +extension String { + public var shouted: String { uppercased() + "!" } +} + +extension Array where Element == Point { + public func centroid() -> Point { + guard !isEmpty else { return Point(x: 0, y: 0) } + let sx = reduce(0) { $0 + $1.x } + let sy = reduce(0) { $0 + $1.y } + return Point(x: sx / Double(count), y: sy / Double(count)) + } +} diff --git a/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift new file mode 100644 index 000000000..6bb24ec62 --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift @@ -0,0 +1,137 @@ +import Foundation + +public protocol Shape: Greeter { + var area: Double { get } + static var sides: Int { get } +} + +open class Polygon { + public let name: String + public private(set) var vertexCount: Int + public static let shared = Polygon(name: "shared", vertexCount: 0) + + public init(name: String, vertexCount: Int) { + self.name = name + self.vertexCount = vertexCount + } + + public convenience init?(name: String) { + guard !name.isEmpty else { return nil } + self.init(name: name, vertexCount: 0) + } + + open func scale(by factor: Double) {} + open func scale(by factor: Int) {} + public func scale(x: Double, y: Double) {} + + public class func make() -> Polygon { Polygon(name: "made", vertexCount: 3) } + public static func describe(_ polygon: Polygon?) -> String { polygon?.name ?? "none" } + + public subscript(index: Int) -> Point { Point(x: Double(index), y: 0) } + + internal func hiddenHelper() {} +} + +public final class Square: Polygon, Shape { + public var side: Double + + public init(side: Double) { + self.side = side + super.init(name: "square", vertexCount: 4) + } + + public var area: Double { side * side } + public static var sides: Int { 4 } + public func greet(name: String) -> String { "Square greets \(name)" } + + override public func scale(by factor: Double) { side *= factor } +} + +public enum ShapeError: Error { + case invalidSide(Double) + case tooManySides(count: Int, limit: Int) + case unknown +} + +public enum Measurement { + case length(Double) + case area(width: Double, height: Double) + case none + + public struct Unit { + public var symbol: String + public init(symbol: String) { self.symbol = symbol } + } + + public var isNone: Bool { + if case .none = self { return true } + return false + } +} + +public struct Ring { + public var inner: Point + public var outer: Point + + public init(inner: Point, outer: Point) { + self.inner = inner + self.outer = outer + } + + public mutating func expand(by delta: Double) { + outer.x += delta + outer.y += delta + } + + public static func + (lhs: Ring, rhs: Ring) -> Ring { + Ring(inner: lhs.inner, outer: rhs.outer) + } +} + +public actor Counter { + public private(set) var value: Int = 0 + public init() {} + public func increment() -> Int { + value += 1 + return value + } + public nonisolated func label() -> String { "counter" } +} + +@MainActor +public final class Canvas { + public init() {} + public func draw(_ shape: any Shape) {} +} + +public final class Loader { + public init() {} + + public func load(path: String) throws -> Data { Data() } + public func fetch(url: URL) async throws -> String { url.absoluteString } + public func wait(seconds: Double) async {} + + public func transform(_ shape: T) -> T { shape } + public func first(of items: [Element]) -> Element? { items.first } + + public func withCompletion(_ completion: @escaping (Result) -> Void) {} + public func each(_ body: (Int) -> Void) {} + + public func lookup(table: [String: Int], key: String) -> Int? { table[key] } + + public func update(_ point: inout Point) { point.x += 1 } + + @available(iOS 16.0, *) + public func modernOnly() {} + + @available(*, deprecated, message: "Use fetch(url:) instead") + public func legacyFetch() {} + + @available(iOS, introduced: 15.0, deprecated: 17.0, renamed: "fetch(url:)") + public func oldFetch() {} +} + +public func makeDefaultPoint() -> Point { Point(x: 0, y: 0) } +public let defaultFlavor: Flavor = .vanilla +public var globalCounter: Int = 0 +public typealias Coordinates = (latitude: Double, longitude: Double) diff --git a/metadata-generator/TestFixtures/SwiftDemo/generate-symbolgraphs.sh b/metadata-generator/TestFixtures/SwiftDemo/generate-symbolgraphs.sh new file mode 100755 index 000000000..d62314f8c --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/generate-symbolgraphs.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Regenerates the checked-in symbol graphs under symbolgraphs/. +# The parser tests snapshot these files, so regenerate only when the fixture +# sources change or when deliberately adopting a new toolchain's output. +set -euo pipefail + +FIXTURE_DIR="$(cd "$(dirname "$0")" && pwd)" +OUT_DIR="$FIXTURE_DIR/symbolgraphs" +WORK_DIR="$(mktemp -d)" +trap 'rm -rf "$WORK_DIR"' EXIT + +SDK_PATH="$(xcrun --sdk iphonesimulator --show-sdk-path)" + +xcrun swiftc \ + -emit-module \ + -emit-module-path "$WORK_DIR/SwiftDemo.swiftmodule" \ + -emit-symbol-graph \ + -emit-symbol-graph-dir "$WORK_DIR" \ + -symbol-graph-minimum-access-level public \ + -module-name SwiftDemo \ + -target arm64-apple-ios15.0-simulator \ + -sdk "$SDK_PATH" \ + "$FIXTURE_DIR"/Sources/SwiftDemo/*.swift + +rm -rf "$OUT_DIR" +mkdir -p "$OUT_DIR" +cp "$WORK_DIR"/*.symbols.json "$OUT_DIR/" + +# Absolute source paths differ per machine; keep the fixture reproducible. +sed -i '' "s#file://$FIXTURE_DIR/#file://#g" "$OUT_DIR"/*.symbols.json + +ls -1 "$OUT_DIR" diff --git a/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json b/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json new file mode 100644 index 000000000..818798d3b --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json @@ -0,0 +1 @@ +{"metadata":{"formatVersion":{"major":0,"minor":6,"patch":0},"generator":"Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)"},"module":{"name":"SwiftDemo","platform":{"architecture":"arm64","environment":"simulator","vendor":"apple","operatingSystem":{"name":"ios","minimumVersion":{"major":15,"minor":0}}}},"symbols":[{"kind":{"identifier":"swift.protocol","displayName":"Protocol"},"identifier":{"precise":"s:9SwiftDemo7GreeterP","interfaceLanguage":"swift"},"pathComponents":["Greeter"],"names":{"title":"Greeter","navigator":[{"kind":"identifier","spelling":"Greeter"}],"subHeading":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Greeter"}]},"declarationFragments":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Greeter"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":0,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Greeter","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":1,"character":9}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo0B0C","interfaceLanguage":"swift"},"pathComponents":["Demo"],"names":{"title":"Demo","navigator":[{"kind":"identifier","spelling":"Demo"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Demo"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Demo"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":4,"character":13}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo0B0CACycfc","interfaceLanguage":"swift"},"pathComponents":["Demo","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":5,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo0B0C5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Demo","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":6,"character":16}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo5PointV","interfaceLanguage":"swift"},"pathComponents":["Point"],"names":{"title":"Point","navigator":[{"kind":"identifier","spelling":"Point"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Point"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Point"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":9,"character":14}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV1xSdvp","interfaceLanguage":"swift"},"pathComponents":["Point","x"],"names":{"title":"x","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":10,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV1ySdvp","interfaceLanguage":"swift"},"pathComponents":["Point","y"],"names":{"title":"y","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":11,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo5PointV1x1yACSd_Sdtcfc","interfaceLanguage":"swift"},"pathComponents":["Point","init(x:y:)"],"names":{"title":"init(x:y:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"x","declarationFragments":[{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},{"name":"y","declarationFragments":[{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":12,"character":11}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor"],"names":{"title":"Flavor","navigator":[{"kind":"identifier","spelling":"Flavor"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Flavor"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Flavor"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","hashValue"],"names":{"title":"hashValue","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","hash(into:)"],"names":{"title":"hash(into:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"into","internalName":"hasher","declarationFragments":[{"kind":"identifier","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftGenerics":{"constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","!=(_:_:)"],"names":{"title":"!=(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"docComment":{"module":"Swift","lines":[{"text":"Returns a Boolean value indicating whether two values are not equal."},{"text":""},{"text":"Inequality is the inverse of equality. For any values `a` and `b`, `a != b`"},{"text":"implies that `a == b` is `false`."},{"text":""},{"text":"This is the default implementation of the not-equal-to operator (`!=`)"},{"text":"for any type that conforms to `Equatable`."},{"text":""},{"text":"- Parameters:"},{"text":" - lhs: A value to compare."},{"text":" - rhs: Another value to compare."}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}],"accessLevel":"public"},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo6FlavorO7vanillayA2CmF","interfaceLanguage":"swift"},"pathComponents":["Flavor","vanilla"],"names":{"title":"Flavor.vanilla","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vanilla"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vanilla"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":31}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo6FlavorO9chocolateyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Flavor","chocolate"],"names":{"title":"Flavor.chocolate","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"chocolate"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"chocolate"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":44}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc","interfaceLanguage":"swift"},"pathComponents":["Flavor","init(rawValue:)"],"names":{"title":"init(rawValue:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"rawValue","declarationFragments":[{"kind":"identifier","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo0B0C5greet4name5timesS2S_SitF","interfaceLanguage":"swift"},"pathComponents":["Demo","greet(name:times:)"],"names":{"title":"greet(name:times:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"times","declarationFragments":[{"kind":"identifier","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.class"},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":1,"character":16}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo0B0C7versionSSvpZ","interfaceLanguage":"swift"},"pathComponents":["Demo","version"],"names":{"title":"version","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"version"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.class"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"version"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":5,"character":22}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV11descriptionSSvp","interfaceLanguage":"swift"},"pathComponents":["Point","description"],"names":{"title":"description","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":9,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV6lengthSdvp","interfaceLanguage":"swift"},"pathComponents":["Point","length"],"names":{"title":"length","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":10,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6FlavorO11descriptionSSvp","interfaceLanguage":"swift"},"pathComponents":["Flavor","description"],"names":{"title":"description","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.enum"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":14,"character":15}}},{"kind":{"identifier":"swift.protocol","displayName":"Protocol"},"identifier":{"precise":"s:9SwiftDemo5ShapeP","interfaceLanguage":"swift"},"pathComponents":["Shape"],"names":{"title":"Shape","navigator":[{"kind":"identifier","spelling":"Shape"}],"subHeading":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Shape"}]},"declarationFragments":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Shape"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Greeter","preciseIdentifier":"s:9SwiftDemo7GreeterP"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":2,"character":16}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5ShapeP4areaSdvp","interfaceLanguage":"swift"},"pathComponents":["Shape","area"],"names":{"title":"area","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":3,"character":8}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo5ShapeP5sidesSivpZ","interfaceLanguage":"swift"},"pathComponents":["Shape","sides"],"names":{"title":"sides","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":4,"character":15}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7PolygonC","interfaceLanguage":"swift"},"pathComponents":["Polygon"],"names":{"title":"Polygon","navigator":[{"kind":"identifier","spelling":"Polygon"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Polygon"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Polygon"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":7,"character":11}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4nameSSvp","interfaceLanguage":"swift"},"pathComponents":["Polygon","name"],"names":{"title":"name","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":8,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC11vertexCountSivp","interfaceLanguage":"swift"},"pathComponents":["Polygon","vertexCount"],"names":{"title":"vertexCount","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":9,"character":28}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC6sharedACvpZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","shared"],"names":{"title":"shared","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shared"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shared"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":10,"character":22}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc","interfaceLanguage":"swift"},"pathComponents":["Polygon","init(name:vertexCount:)"],"names":{"title":"init(name:vertexCount:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"vertexCount","declarationFragments":[{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":12,"character":11}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4nameACSgSS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Polygon","init(name:)"],"names":{"title":"init(name:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"convenience"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":17,"character":23}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":22,"character":14}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale2byySi_tF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":23,"character":14}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(x:y:)"],"names":{"title":"scale(x:y:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"x","declarationFragments":[{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},{"name":"y","declarationFragments":[{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":24,"character":16}}},{"kind":{"identifier":"swift.type.method","displayName":"Type Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4makeACyFZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","make()"],"names":{"title":"make()","subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"make"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"make"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":26,"character":22}}},{"kind":{"identifier":"swift.type.method","displayName":"Type Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC8describeySSACSgFZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","describe(_:)"],"names":{"title":"describe(_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"describe"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"polygon","declarationFragments":[{"kind":"identifier","spelling":"polygon"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"describe"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"polygon"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":27,"character":23}}},{"kind":{"identifier":"swift.subscript","displayName":"Instance Subscript"},"identifier":{"precise":"s:9SwiftDemo7PolygonCyAA5PointVSicip","interfaceLanguage":"swift"},"pathComponents":["Polygon","subscript(_:)"],"names":{"title":"subscript(_:)","subHeading":[{"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"parameters":[{"name":"index","declarationFragments":[{"kind":"identifier","spelling":"index"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"index"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":29,"character":11}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6SquareC","interfaceLanguage":"swift"},"pathComponents":["Square"],"names":{"title":"Square","navigator":[{"kind":"identifier","spelling":"Square"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Square"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Square"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":34,"character":19}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC4sideSdvp","interfaceLanguage":"swift"},"pathComponents":["Square","side"],"names":{"title":"side","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":35,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6SquareC4sideACSd_tcfc","interfaceLanguage":"swift"},"pathComponents":["Square","init(side:)"],"names":{"title":"init(side:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"side","declarationFragments":[{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":37,"character":11}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC4areaSdvp","interfaceLanguage":"swift"},"pathComponents":["Square","area"],"names":{"title":"area","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":42,"character":15}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC5sidesSivpZ","interfaceLanguage":"swift"},"pathComponents":["Square","sides"],"names":{"title":"sides","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":43,"character":22}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6SquareC5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Square","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":44,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6SquareC5scale2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Square","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"override"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":46,"character":25}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO","interfaceLanguage":"swift"},"pathComponents":["ShapeError"],"names":{"title":"ShapeError","navigator":[{"kind":"identifier","spelling":"ShapeError"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"ShapeError"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"ShapeError"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":49,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO","interfaceLanguage":"swift"},"pathComponents":["ShapeError","localizedDescription"],"names":{"title":"localizedDescription","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"localizedDescription"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"docComment":{"module":"Foundation","lines":[{"text":"Retrieve the localized description for this error."}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"localizedDescription"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":8,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":10}},{"domain":"tvOS","introduced":{"major":9,"minor":0}},{"domain":"watchOS","introduced":{"major":2,"minor":0}}]},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","invalidSide(_:)"],"names":{"title":"ShapeError.invalidSide(_:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"invalidSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"invalidSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":50,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","tooManySides(count:limit:)"],"names":{"title":"ShapeError.tooManySides(count:limit:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"tooManySides"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"count"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"limit"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"tooManySides"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"count"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"limit"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":51,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO7unknownyA2CmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","unknown"],"names":{"title":"ShapeError.unknown","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"unknown"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"unknown"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":52,"character":9}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO","interfaceLanguage":"swift"},"pathComponents":["Measurement"],"names":{"title":"Measurement","navigator":[{"kind":"identifier","spelling":"Measurement"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Measurement"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Measurement"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":55,"character":12}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO6lengthyACSdcACmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","length(_:)"],"names":{"title":"Measurement.length(_:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":56,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","area(width:height:)"],"names":{"title":"Measurement.area(width:height:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"width"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"height"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"width"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"height"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":57,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4noneyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","none"],"names":{"title":"Measurement.none","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":58,"character":9}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit"],"names":{"title":"Measurement.Unit","navigator":[{"kind":"identifier","spelling":"Unit"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Unit"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Unit"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":60,"character":18}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit","symbol"],"names":{"title":"symbol","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":61,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit","init(symbol:)"],"names":{"title":"init(symbol:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"symbol","declarationFragments":[{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":62,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO6isNoneSbvp","interfaceLanguage":"swift"},"pathComponents":["Measurement","isNone"],"names":{"title":"isNone","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"isNone"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"isNone"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":65,"character":15}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo4RingV","interfaceLanguage":"swift"},"pathComponents":["Ring"],"names":{"title":"Ring","navigator":[{"kind":"identifier","spelling":"Ring"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Ring"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Ring"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":71,"character":14}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo4RingV5innerAA5PointVvp","interfaceLanguage":"swift"},"pathComponents":["Ring","inner"],"names":{"title":"inner","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":72,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo4RingV5outerAA5PointVvp","interfaceLanguage":"swift"},"pathComponents":["Ring","outer"],"names":{"title":"outer","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":73,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc","interfaceLanguage":"swift"},"pathComponents":["Ring","init(inner:outer:)"],"names":{"title":"init(inner:outer:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"inner","declarationFragments":[{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},{"name":"outer","declarationFragments":[{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":75,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo4RingV6expand2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Ring","expand(by:)"],"names":{"title":"expand(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"expand"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"delta","declarationFragments":[{"kind":"identifier","spelling":"delta"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"mutating"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"expand"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"delta"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":80,"character":25}}},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:9SwiftDemo4RingV1poiyA2C_ACtFZ","interfaceLanguage":"swift"},"pathComponents":["Ring","+(_:_:)"],"names":{"title":"+(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"+"},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"+"},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":85,"character":23}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter"],"names":{"title":"Counter","navigator":[{"kind":"identifier","spelling":"Counter"}],"subHeading":[{"kind":"keyword","spelling":"actor"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Counter"}]},"declarationFragments":[{"kind":"keyword","spelling":"actor"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Counter"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":90,"character":13}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","withSerialExecutor(_:)"],"names":{"title":"withSerialExecutor(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">((any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Perform an operation with the actor's ``SerialExecutor``."},{"text":""},{"text":"This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while"},{"text":"retaining the actor for the duration of the operation. This is to ensure the lifetime"},{"text":"of the executor while performing the operation."}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1},{"name":"E","index":1,"depth":1}],"constraints":[{"kind":"conformance","lhs":"E","rhs":"Error","rhsPrecise":"s:s5ErrorP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Error","preciseIdentifier":"s:s5ErrorP"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : ~Copyable"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","withSerialExecutor(_:)"],"names":{"title":"withSerialExecutor(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"keyword","spelling":"nonisolated(nonsending)"},{"kind":"text","spelling":" (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Perform an operation with the actor's ``SerialExecutor``."},{"text":""},{"text":"This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while"},{"text":"retaining the actor for the duration of the operation. This is to ensure the lifetime"},{"text":"of the executor while performing the operation."}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1},{"name":"E","index":1,"depth":1}],"constraints":[{"kind":"conformance","lhs":"E","rhs":"Error","rhsPrecise":"s:s5ErrorP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"nonisolated(nonsending)"},{"kind":"text","spelling":" (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Error","preciseIdentifier":"s:s5ErrorP"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : ~Copyable"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","preconditionIsolated(_:file:line:)"],"names":{"title":"preconditionIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"preconditionIsolated"},{"kind":"text","spelling":"("},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":")"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Stops program execution if the current task is not executing on this"},{"text":"actor's serial executor."},{"text":""},{"text":"This function's effect varies depending on the build flag used:"},{"text":""},{"text":"* In playgrounds and `-Onone` builds (the default for Xcode's Debug"},{"text":" configuration), stops program execution in a debuggable state after"},{"text":" printing `message`."},{"text":""},{"text":"* In `-O` builds (the default for Xcode's Release configuration), stops"},{"text":" program execution."},{"text":""},{"text":"- Note: Because this check is performed against the actor's serial executor,"},{"text":" if another actor uses the same serial executor--by using"},{"text":" that actor's serial executor as its own ``Actor/unownedExecutor``--this"},{"text":" check will succeed. From a concurrency safety perspective, the"},{"text":" serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - message: The message to print if the assertion fails."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."}]},"functionSignature":{"parameters":[{"name":"message","declarationFragments":[{"kind":"identifier","spelling":"message"},{"kind":"text","spelling":": () -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"text","spelling":"@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\n"},{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"preconditionIsolated"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"message"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" = String(), "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":")"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","assertIsolated(_:file:line:)"],"names":{"title":"assertIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assertIsolated"},{"kind":"text","spelling":"("},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":")"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Stops program execution if the current task is not executing on this"},{"text":"actor's serial executor."},{"text":""},{"text":"This function's effect varies depending on the build flag used:"},{"text":""},{"text":"* In playgrounds and `-Onone` builds (the default for Xcode's Debug"},{"text":" configuration), stops program execution in a debuggable state after"},{"text":" printing `message`."},{"text":""},{"text":"* In `-O` builds (the default for Xcode's Release configuration),"},{"text":" the isolation check is not performed and there are no effects."},{"text":""},{"text":"- Note: This check is performed against the actor's serial executor,"},{"text":" meaning that / if another actor uses the same serial executor--by using"},{"text":" that actor's serial executor as its own ``Actor/unownedExecutor``--this"},{"text":" check will succeed , as from a concurrency safety perspective, the"},{"text":" serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - message: The message to print if the assertion fails."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."}]},"functionSignature":{"parameters":[{"name":"message","declarationFragments":[{"kind":"identifier","spelling":"message"},{"kind":"text","spelling":": () -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"text","spelling":"@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\n"},{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assertIsolated"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"message"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" = String(), "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":")"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","assumeIsolated(_:file:line:)"],"names":{"title":"assumeIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assumeIsolated"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">(("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"rethrows"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Assume that the current task is executing on this actor's serial executor,"},{"text":"or stop program execution otherwise."},{"text":""},{"text":"You call this method to *assume and verify* that the currently"},{"text":"executing synchronous function is actually executing on the serial"},{"text":"executor of this actor."},{"text":""},{"text":"If that is the case, the operation is invoked with an `isolated` version"},{"text":"of the actor, allowing synchronous access to actor local state without"},{"text":"hopping through asynchronous boundaries."},{"text":""},{"text":"If the current context is not running on the actor's serial executor, or"},{"text":"if the actor is a reference to a remote actor, this method will crash"},{"text":"with a fatal error (similar to ``preconditionIsolated(_:file:line:)``)."},{"text":""},{"text":"Note that this check is performed against the passed in actor's serial"},{"text":"executor, meaning that if another actor uses the same serial executor--by"},{"text":"using that actor's ``Actor/unownedExecutor`` as its own"},{"text":"``Actor/unownedExecutor``--this check will succeed, as from a concurrency"},{"text":"safety perspective, the serial executor guarantees mutual exclusion of"},{"text":"those two actors."},{"text":""},{"text":"This method can only be used from synchronous functions, as asynchronous"},{"text":"functions should instead perform a normal method call to the actor, which"},{"text":"will hop task execution to the target actor if necessary."},{"text":""},{"text":"- Note: This check is performed against the actor's serial executor,"},{"text":" meaning that / if another actor uses the same serial executor--by using"},{"text":" another actor's executor as its own ``Actor/unownedExecutor``"},{"text":" --this check will succeed , as from a concurrency safety perspective,"},{"text":" the serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - operation: the operation that will be executed if the current context"},{"text":" is executing on the actors serial executor."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."},{"text":"- Returns: the return value of the `operation`"},{"text":"- Throws: rethrows the `Error` thrown by the operation if it threw"}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": ("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1}],"constraints":[{"kind":"conformance","lhs":"T","rhs":"Sendable","rhsPrecise":"s:s8SendableP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assumeIsolated"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": ("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"rethrows"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Sendable","preciseIdentifier":"s:s8SendableP"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7CounterC5valueSivp","interfaceLanguage":"swift"},"pathComponents":["Counter","value"],"names":{"title":"value","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":91,"character":28}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7CounterCACycfc","interfaceLanguage":"swift"},"pathComponents":["Counter","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":92,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7CounterC9incrementSiyF","interfaceLanguage":"swift"},"pathComponents":["Counter","increment()"],"names":{"title":"increment()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"increment"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"increment"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":93,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7CounterC5labelSSyF","interfaceLanguage":"swift"},"pathComponents":["Counter","label()"],"names":{"title":"label()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"label"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"label"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":97,"character":28}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6CanvasC","interfaceLanguage":"swift"},"pathComponents":["Canvas"],"names":{"title":"Canvas","navigator":[{"kind":"identifier","spelling":"Canvas"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Canvas"}]},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Canvas"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":101,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6CanvasCACycfc","interfaceLanguage":"swift"},"pathComponents":["Canvas","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":102,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF","interfaceLanguage":"swift"},"pathComponents":["Canvas","draw(_:)"],"names":{"title":"draw(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"draw"},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"shape","declarationFragments":[{"kind":"identifier","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"draw"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":103,"character":16}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6LoaderC","interfaceLanguage":"swift"},"pathComponents":["Loader"],"names":{"title":"Loader","navigator":[{"kind":"identifier","spelling":"Loader"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Loader"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Loader"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":106,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6LoaderCACycfc","interfaceLanguage":"swift"},"pathComponents":["Loader","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":107,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF","interfaceLanguage":"swift"},"pathComponents":["Loader","load(path:)"],"names":{"title":"load(path:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}]},"functionSignature":{"parameters":[{"name":"path","declarationFragments":[{"kind":"identifier","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":109,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF","interfaceLanguage":"swift"},"pathComponents":["Loader","fetch(url:)"],"names":{"title":"fetch(url:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"fetch"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"url","declarationFragments":[{"kind":"identifier","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"fetch"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":110,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF","interfaceLanguage":"swift"},"pathComponents":["Loader","wait(seconds:)"],"names":{"title":"wait(seconds:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"wait"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"}]},"functionSignature":{"parameters":[{"name":"seconds","declarationFragments":[{"kind":"identifier","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"wait"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":111,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF","interfaceLanguage":"swift"},"pathComponents":["Loader","transform(_:)"],"names":{"title":"transform(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"transform"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"}]},"functionSignature":{"parameters":[{"name":"shape","declarationFragments":[{"kind":"identifier","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":0}],"constraints":[{"kind":"conformance","lhs":"T","rhs":"Shape","rhsPrecise":"s:9SwiftDemo5ShapeP"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"transform"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":113,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF","interfaceLanguage":"swift"},"pathComponents":["Loader","first(of:)"],"names":{"title":"first(of:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"first"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"Element"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"of"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]) -> "},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"of","internalName":"items","declarationFragments":[{"kind":"identifier","spelling":"items"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Element"},{"kind":"text","spelling":"?"}]},"swiftGenerics":{"parameters":[{"name":"Element","index":0,"depth":0}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"first"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"Element"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"of"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"items"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]) -> "},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":114,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF","interfaceLanguage":"swift"},"pathComponents":["Loader","withCompletion(_:)"],"names":{"title":"withCompletion(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withCompletion"},{"kind":"text","spelling":"(("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"completion","declarationFragments":[{"kind":"identifier","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" ("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withCompletion"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" ("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":116,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4eachyyySiXEF","interfaceLanguage":"swift"},"pathComponents":["Loader","each(_:)"],"names":{"title":"each(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"each"},{"kind":"text","spelling":"(("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"body","declarationFragments":[{"kind":"identifier","spelling":"body"},{"kind":"text","spelling":": ("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"each"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"body"},{"kind":"text","spelling":": ("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":117,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF","interfaceLanguage":"swift"},"pathComponents":["Loader","lookup(table:key:)"],"names":{"title":"lookup(table:key:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"lookup"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"], "},{"kind":"externalParam","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"table","declarationFragments":[{"kind":"identifier","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"]"}]},{"name":"key","declarationFragments":[{"kind":"identifier","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"lookup"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"], "},{"kind":"externalParam","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":119,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC6updateyyAA5PointVzF","interfaceLanguage":"swift"},"pathComponents":["Loader","update(_:)"],"names":{"title":"update(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"update"},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"point","declarationFragments":[{"kind":"identifier","spelling":"point"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"update"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"point"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":121,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC10modernOnlyyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","modernOnly()"],"names":{"title":"modernOnly()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"modernOnly"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"modernOnly"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":16,"minor":0}}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":124,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC11legacyFetchyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","legacyFetch()"],"names":{"title":"legacyFetch()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"legacyFetch"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"legacyFetch"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"*","message":"Use fetch(url:) instead","isUnconditionallyDeprecated":true}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":127,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC8oldFetchyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","oldFetch()"],"names":{"title":"oldFetch()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"oldFetch"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"oldFetch"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":15,"minor":0},"deprecated":{"major":17,"minor":0},"renamed":"fetch(url:)"}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":130,"character":16}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo16makeDefaultPointAA0E0VyF","interfaceLanguage":"swift"},"pathComponents":["makeDefaultPoint()"],"names":{"title":"makeDefaultPoint()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"makeDefaultPoint"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"makeDefaultPoint"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":133,"character":12}}},{"kind":{"identifier":"swift.var","displayName":"Global Variable"},"identifier":{"precise":"s:9SwiftDemo13defaultFlavorAA0D0Ovp","interfaceLanguage":"swift"},"pathComponents":["defaultFlavor"],"names":{"title":"defaultFlavor","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"defaultFlavor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Flavor","preciseIdentifier":"s:9SwiftDemo6FlavorO"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"defaultFlavor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Flavor","preciseIdentifier":"s:9SwiftDemo6FlavorO"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":134,"character":11}}},{"kind":{"identifier":"swift.var","displayName":"Global Variable"},"identifier":{"precise":"s:9SwiftDemo13globalCounterSivp","interfaceLanguage":"swift"},"pathComponents":["globalCounter"],"names":{"title":"globalCounter","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"globalCounter"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"globalCounter"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":135,"character":11}}},{"kind":{"identifier":"swift.typealias","displayName":"Type Alias"},"identifier":{"precise":"s:9SwiftDemo11Coordinatesa","interfaceLanguage":"swift"},"pathComponents":["Coordinates"],"names":{"title":"Coordinates","navigator":[{"kind":"identifier","spelling":"Coordinates"}],"subHeading":[{"kind":"keyword","spelling":"typealias"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Coordinates"}]},"declarationFragments":[{"kind":"keyword","spelling":"typealias"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Coordinates"},{"kind":"text","spelling":" = (latitude"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", longitude"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":136,"character":17}}}],"relationships":[{"kind":"requirementOf","source":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","target":"s:9SwiftDemo7GreeterP"},{"kind":"conformsTo","source":"s:9SwiftDemo0B0C","target":"s:9SwiftDemo7GreeterP"},{"kind":"memberOf","source":"s:9SwiftDemo0B0CACycfc","target":"s:9SwiftDemo0B0C"},{"kind":"memberOf","source":"s:9SwiftDemo0B0C5greet4nameS2S_tF","target":"s:9SwiftDemo0B0C","sourceOrigin":{"identifier":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","displayName":"Greeter.greet(name:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s23CustomStringConvertibleP","targetFallback":"Swift.CustomStringConvertible"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1xSdvp","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1ySdvp","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1x1yACSd_Sdtcfc","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp","displayName":"RawRepresentable.hashValue"}},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF","displayName":"RawRepresentable.hash(into:)"}},{"kind":"memberOf","source":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ","displayName":"Equatable.!=(_:_:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SQ","targetFallback":"Swift.Equatable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SH","targetFallback":"Swift.Hashable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SY","targetFallback":"Swift.RawRepresentable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s23CustomStringConvertibleP","targetFallback":"Swift.CustomStringConvertible"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO7vanillayA2CmF","target":"s:9SwiftDemo6FlavorO"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO9chocolateyA2CmF","target":"s:9SwiftDemo6FlavorO"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SY8rawValuexSg03RawB0Qz_tcfc","displayName":"RawRepresentable.init(rawValue:)"}},{"kind":"memberOf","source":"s:9SwiftDemo0B0C5greet4name5timesS2S_SitF","target":"s:9SwiftDemo0B0C"},{"kind":"memberOf","source":"s:9SwiftDemo0B0C7versionSSvpZ","target":"s:9SwiftDemo0B0C"},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s9EscapableP","targetFallback":"Swift.Escapable"},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s8CopyableP","targetFallback":"Swift.Copyable"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV11descriptionSSvp","target":"s:9SwiftDemo5PointV","sourceOrigin":{"identifier":"s:s23CustomStringConvertibleP11descriptionSSvp","displayName":"CustomStringConvertible.description"}},{"kind":"memberOf","source":"s:9SwiftDemo5PointV6lengthSdvp","target":"s:9SwiftDemo5PointV"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s9EscapableP","targetFallback":"Swift.Escapable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s8CopyableP","targetFallback":"Swift.Copyable"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO11descriptionSSvp","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:s23CustomStringConvertibleP11descriptionSSvp","displayName":"CustomStringConvertible.description"}},{"kind":"conformsTo","source":"s:9SwiftDemo5ShapeP","target":"s:9SwiftDemo7GreeterP"},{"kind":"requirementOf","source":"s:9SwiftDemo5ShapeP4areaSdvp","target":"s:9SwiftDemo5ShapeP"},{"kind":"requirementOf","source":"s:9SwiftDemo5ShapeP5sidesSivpZ","target":"s:9SwiftDemo5ShapeP"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4nameSSvp","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC11vertexCountSivp","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC6sharedACvpZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4nameACSgSS_tcfc","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale2byySd_tF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale2byySi_tF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4makeACyFZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC8describeySSACSgFZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonCyAA5PointVSicip","target":"s:9SwiftDemo7PolygonC"},{"kind":"conformsTo","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo5ShapeP"},{"kind":"conformsTo","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo7GreeterP"},{"kind":"inheritsFrom","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4sideSdvp","target":"s:9SwiftDemo6SquareC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4sideACSd_tcfc","target":"s:9SwiftDemo6SquareC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4areaSdvp","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo5ShapeP4areaSdvp","displayName":"Shape.area"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5sidesSivpZ","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo5ShapeP5sidesSivpZ","displayName":"Shape.sides"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5greet4nameS2S_tF","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","displayName":"Greeter.greet(name:)"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5scale2byySd_tF","target":"s:9SwiftDemo6SquareC"},{"kind":"overrides","source":"s:9SwiftDemo6SquareC5scale2byySd_tF","target":"s:9SwiftDemo7PolygonC5scale2byySd_tF"},{"kind":"memberOf","source":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO","target":"s:9SwiftDemo10ShapeErrorO","sourceOrigin":{"identifier":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp","displayName":"Error.localizedDescription"}},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s5ErrorP","targetFallback":"Swift.Error"},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s16SendableMetatypeP","targetFallback":"Swift.SendableMetatype"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO7unknownyA2CmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO6lengthyACSdcACmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4noneyA2CmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp","target":"s:9SwiftDemo11MeasurementO4UnitV"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc","target":"s:9SwiftDemo11MeasurementO4UnitV"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO6isNoneSbvp","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5innerAA5PointVvp","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5outerAA5PointVvp","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV6expand2byySd_tF","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV1poiyA2C_ACtFZ","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF","displayName":"Actor.withSerialExecutor(_:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF","displayName":"Actor.withSerialExecutor(_:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF","displayName":"Actor.preconditionIsolated(_:file:line:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF","displayName":"Actor.assertIsolated(_:file:line:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF","displayName":"Actor.assumeIsolated(_:file:line:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:ScA","targetFallback":"_Concurrency.Actor"},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:s16SendableMetatypeP","targetFallback":"Swift.SendableMetatype"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC5valueSivp","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterCACycfc","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC9incrementSiyF","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC5labelSSyF","target":"s:9SwiftDemo7CounterC"},{"kind":"conformsTo","source":"s:9SwiftDemo6CanvasC","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"memberOf","source":"s:9SwiftDemo6CanvasCACycfc","target":"s:9SwiftDemo6CanvasC"},{"kind":"memberOf","source":"s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF","target":"s:9SwiftDemo6CanvasC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderCACycfc","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4eachyyySiXEF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC6updateyyAA5PointVzF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC10modernOnlyyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC11legacyFetchyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC8oldFetchyyF","target":"s:9SwiftDemo6LoaderC"}]} \ No newline at end of file diff --git a/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo@Swift.symbols.json b/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo@Swift.symbols.json new file mode 100644 index 000000000..8ef8982db --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo@Swift.symbols.json @@ -0,0 +1 @@ +{"metadata":{"formatVersion":{"major":0,"minor":6,"patch":0},"generator":"Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)"},"module":{"name":"SwiftDemo","platform":{"architecture":"arm64","environment":"simulator","vendor":"apple","operatingSystem":{"name":"ios","minimumVersion":{"major":15,"minor":0}}}},"symbols":[{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:SS9SwiftDemoE7shoutedSSvp","interfaceLanguage":"swift"},"pathComponents":["String","shouted"],"names":{"title":"shouted","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shouted"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shouted"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":18,"character":15}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:Sa9SwiftDemoAA5PointVRszlE8centroidACyF","interfaceLanguage":"swift"},"pathComponents":["Array","centroid()"],"names":{"title":"centroid()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"centroid"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"swiftGenerics":{"parameters":[{"name":"Element","index":0,"depth":0}],"constraints":[{"kind":"sameType","lhs":"Element","rhs":"Point","rhsPrecise":"s:9SwiftDemo5PointV"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.struct","constraints":[{"kind":"sameType","lhs":"Element","rhs":"Point","rhsPrecise":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"centroid"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":22,"character":16}}}],"relationships":[{"kind":"memberOf","source":"s:SS9SwiftDemoE7shoutedSSvp","target":"s:SS","targetFallback":"Swift.String"},{"kind":"memberOf","source":"s:Sa9SwiftDemoAA5PointVRszlE8centroidACyF","target":"s:Sa","targetFallback":"Swift.Array"}]} \ No newline at end of file diff --git a/metadata-generator/src/CMakeLists.txt b/metadata-generator/src/CMakeLists.txt index 5942ac24f..ae2e329df 100644 --- a/metadata-generator/src/CMakeLists.txt +++ b/metadata-generator/src/CMakeLists.txt @@ -37,7 +37,8 @@ set(GENERATOR_HEADERS Yaml/YamlSerializer.h # Swift support - Swift/SymbolGraphParser.h + Swift/SwiftIR.h + Swift/SymbolGraphLoader.h TypeScript/SwiftDefinitionWriter.h ) @@ -69,7 +70,8 @@ set(GENERATOR_SOURCES Utils/memoryStream.cpp # Swift support - Swift/SymbolGraphParser.cpp + Swift/SwiftIR.cpp + Swift/SymbolGraphLoader.cpp TypeScript/SwiftDefinitionWriter.cpp ) diff --git a/metadata-generator/src/Swift/SwiftIR.cpp b/metadata-generator/src/Swift/SwiftIR.cpp new file mode 100644 index 000000000..62d1171fd --- /dev/null +++ b/metadata-generator/src/Swift/SwiftIR.cpp @@ -0,0 +1,341 @@ +#include "SwiftIR.h" + +#include +#include +#include + +namespace Swift { + +const char* toString(SymbolKind kind) { + switch (kind) { + case SymbolKind::Class: + return "class"; + case SymbolKind::Actor: + return "actor"; + case SymbolKind::Struct: + return "struct"; + case SymbolKind::Enum: + return "enum"; + case SymbolKind::Protocol: + return "protocol"; + case SymbolKind::EnumCase: + return "enumCase"; + case SymbolKind::Initializer: + return "initializer"; + case SymbolKind::Deinitializer: + return "deinitializer"; + case SymbolKind::InstanceMethod: + return "instanceMethod"; + case SymbolKind::TypeMethod: + return "typeMethod"; + case SymbolKind::Operator: + return "operator"; + case SymbolKind::InstanceProperty: + return "instanceProperty"; + case SymbolKind::TypeProperty: + return "typeProperty"; + case SymbolKind::InstanceSubscript: + return "instanceSubscript"; + case SymbolKind::TypeSubscript: + return "typeSubscript"; + case SymbolKind::Function: + return "function"; + case SymbolKind::Variable: + return "variable"; + case SymbolKind::TypeAlias: + return "typeAlias"; + case SymbolKind::AssociatedType: + return "associatedType"; + case SymbolKind::Macro: + return "macro"; + case SymbolKind::Extension: + return "extension"; + case SymbolKind::Unknown: + return "unknown"; + } + return "unknown"; +} + +bool isNominalType(SymbolKind kind) { + switch (kind) { + case SymbolKind::Class: + case SymbolKind::Actor: + case SymbolKind::Struct: + case SymbolKind::Enum: + case SymbolKind::Protocol: + return true; + default: + return false; + } +} + +const char* toString(AccessLevel level) { + switch (level) { + case AccessLevel::Private: + return "private"; + case AccessLevel::FilePrivate: + return "fileprivate"; + case AccessLevel::Internal: + return "internal"; + case AccessLevel::Package: + return "package"; + case AccessLevel::Public: + return "public"; + case AccessLevel::Open: + return "open"; + case AccessLevel::Unknown: + return "unknown"; + } + return "unknown"; +} + +const Symbol* Module::find(const std::string& preciseId) const { + auto it = symbols.find(preciseId); + return it == symbols.end() ? nullptr : &it->second; +} + +bool ModuleSet::hasErrors() const { + for (const auto& diagnostic : diagnostics) { + if (diagnostic.severity == Severity::Error) { + return true; + } + } + return false; +} + +namespace { + +using llvm::json::OStream; + +std::string versionString(const Version& version) { + return std::to_string(version.major) + "." + std::to_string(version.minor) + + "." + std::to_string(version.patch); +} + +void writeStringArray(OStream& out, llvm::StringRef key, + const std::vector& values) { + if (values.empty()) { + return; + } + out.attributeArray(key, [&] { + for (const auto& value : values) { + out.value(value); + } + }); +} + +void writeNonEmpty(OStream& out, llvm::StringRef key, + const std::string& value) { + if (!value.empty()) { + out.attribute(key, value); + } +} + +void writeFlag(OStream& out, llvm::StringRef key, bool value) { + if (value) { + out.attribute(key, true); + } +} + +void writeTypeRef(OStream& out, llvm::StringRef key, const TypeRef& type) { + out.attributeObject(key, [&] { + out.attribute("spelling", type.spelling); + std::vector references; + for (const auto& fragment : type.fragments) { + if (!fragment.preciseIdentifier.empty()) { + references.push_back(fragment.preciseIdentifier); + } + } + writeStringArray(out, "references", references); + }); +} + +void writeConstraints(OStream& out, llvm::StringRef key, + const std::vector& constraints) { + if (constraints.empty()) { + return; + } + out.attributeArray(key, [&] { + for (const auto& constraint : constraints) { + out.object([&] { + out.attribute("kind", constraint.kind); + out.attribute("lhs", constraint.lhs); + out.attribute("rhs", constraint.rhs); + writeNonEmpty(out, "rhsPrecise", constraint.rhsPrecise); + }); + } + }); +} + +void writeSymbol(OStream& out, const Symbol& symbol) { + out.object([&] { + out.attribute("id", symbol.preciseId); + out.attribute("kind", toString(symbol.kind)); + out.attribute("path", llvm::join(symbol.pathComponents, ".")); + out.attribute("name", symbol.name); + out.attribute("access", toString(symbol.access)); + out.attribute("declaration", symbol.declarationText); + writeStringArray(out, "attributes", symbol.attributes); + writeStringArray(out, "modifiers", symbol.modifiers); + writeFlag(out, "static", symbol.isStatic); + writeFlag(out, "synthesized", symbol.isSynthesized); + writeFlag(out, "protocolRequirement", symbol.isProtocolRequirement); + writeFlag(out, "optionalRequirement", symbol.isOptionalRequirement); + + if (!symbol.parameters.empty()) { + out.attributeArray("parameters", [&] { + for (const auto& parameter : symbol.parameters) { + out.object([&] { + writeNonEmpty(out, "label", parameter.label); + writeNonEmpty(out, "internalName", parameter.internalName); + writeTypeRef(out, "type", parameter.type); + writeNonEmpty(out, "modifier", parameter.modifier); + writeStringArray(out, "attributes", parameter.attributes); + writeNonEmpty(out, "default", parameter.defaultValue); + writeFlag(out, "variadic", parameter.isVariadic); + }); + } + }); + } + if (symbol.returnType) { + writeTypeRef(out, "returns", *symbol.returnType); + } + writeFlag(out, "async", symbol.isAsync); + writeFlag(out, "throws", symbol.isThrowing); + writeFlag(out, "rethrows", symbol.isRethrowing); + if (!symbol.thrownType.empty()) { + writeTypeRef(out, "thrownType", symbol.thrownType); + } + writeFlag(out, "failable", symbol.isFailable); + writeFlag(out, "implicitlyUnwrappedFailable", + symbol.isImplicitlyUnwrappedFailable); + if (symbol.valueType) { + writeTypeRef(out, "valueType", *symbol.valueType); + out.attribute("settable", symbol.isSettable); + writeFlag(out, "let", symbol.isLet); + } + if (symbol.aliasedType) { + writeTypeRef(out, "aliasedType", *symbol.aliasedType); + } + + if (!symbol.genericParameters.empty()) { + out.attributeArray("genericParameters", [&] { + for (const auto& parameter : symbol.genericParameters) { + out.object([&] { + out.attribute("name", parameter.name); + out.attribute("depth", parameter.depth); + out.attribute("index", parameter.index); + }); + } + }); + } + writeConstraints(out, "genericConstraints", symbol.genericConstraints); + + if (symbol.extension) { + out.attributeObject("extension", [&] { + out.attribute("extendedModule", symbol.extension->extendedModule); + writeNonEmpty(out, "typeKind", symbol.extension->typeKind); + writeConstraints(out, "constraints", symbol.extension->constraints); + }); + } + + if (!symbol.availability.empty()) { + out.attributeArray("availability", [&] { + for (const auto& availability : symbol.availability) { + out.object([&] { + out.attribute("domain", availability.domain); + if (availability.introduced) { + out.attribute("introduced", + versionString(*availability.introduced)); + } + if (availability.deprecated) { + out.attribute("deprecated", + versionString(*availability.deprecated)); + } + if (availability.obsoleted) { + out.attribute("obsoleted", + versionString(*availability.obsoleted)); + } + writeNonEmpty(out, "message", availability.message); + writeNonEmpty(out, "renamed", availability.renamed); + writeFlag(out, "unconditionallyDeprecated", + availability.isUnconditionallyDeprecated); + writeFlag(out, "unconditionallyUnavailable", + availability.isUnconditionallyUnavailable); + }); + } + }); + } + + if (symbol.location) { + out.attribute("location", symbol.location->uri + ":" + + std::to_string(symbol.location->line) + + ":" + + std::to_string(symbol.location->character)); + } + out.attribute("graph", symbol.sourceGraph); + + writeNonEmpty(out, "parent", symbol.parentId); + writeStringArray(out, "members", symbol.memberIds); + writeStringArray(out, "conformances", symbol.conformances); + writeNonEmpty(out, "superclass", symbol.superclassId); + writeNonEmpty(out, "overrides", symbol.overriddenId); + writeNonEmpty(out, "sourceOrigin", symbol.sourceOriginId); + writeStringArray(out, "defaultImplementationOf", + symbol.defaultImplementationOf); + }); +} + +} // namespace + +std::string dumpModuleJSON(const Module& module) { + std::string result; + llvm::raw_string_ostream stream(result); + OStream out(stream, 2); + out.object([&] { + out.attribute("module", module.name); + out.attribute("formatVersion", versionString(module.formatVersion)); + out.attributeObject("platform", [&] { + writeNonEmpty(out, "architecture", module.platform.architecture); + writeNonEmpty(out, "vendor", module.platform.vendor); + writeNonEmpty(out, "operatingSystem", module.platform.operatingSystem); + writeNonEmpty(out, "environment", module.platform.environment); + if (module.platform.minimumVersion) { + out.attribute("minimumVersion", + versionString(*module.platform.minimumVersion)); + } + }); + writeStringArray(out, "graphFiles", module.graphFiles); + writeStringArray(out, "topLevel", module.topLevelIds); + + out.attributeArray("externalTypes", [&] { + for (const auto& entry : module.externalTypes) { + const auto& external = entry.second; + out.object([&] { + out.attribute("id", external.preciseId); + out.attribute("qualifiedName", external.qualifiedName); + writeNonEmpty(out, "extendedModule", external.extendedModule); + writeNonEmpty(out, "typeKind", external.typeKind); + writeStringArray(out, "members", external.memberIds); + }); + } + }); + + out.attributeObject("externalNames", [&] { + for (const auto& entry : module.externalNames) { + out.attribute(entry.first, entry.second); + } + }); + + out.attributeArray("symbols", [&] { + for (const auto& entry : module.symbols) { + writeSymbol(out, entry.second); + } + }); + }); + stream << "\n"; + stream.flush(); + return result; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SwiftIR.h b/metadata-generator/src/Swift/SwiftIR.h new file mode 100644 index 000000000..b77f67edb --- /dev/null +++ b/metadata-generator/src/Swift/SwiftIR.h @@ -0,0 +1,264 @@ +#pragma once + +#include +#include +#include +#include + +namespace Swift { + +// One `declarationFragments` entry. `preciseIdentifier` is the USR of the +// referenced declaration for typeIdentifier fragments, empty otherwise. +struct Fragment { + std::string kind; + std::string spelling; + std::string preciseIdentifier; +}; + +using Fragments = std::vector; + +// A type as written in a declaration. Kept unresolved here: `spelling` is the +// source text, `fragments` keep the per-identifier USRs that a type resolver +// needs to map nominal references back to symbols. +struct TypeRef { + std::string spelling; + Fragments fragments; + + bool empty() const { return spelling.empty(); } +}; + +enum class SymbolKind { + Class, + Actor, + Struct, + Enum, + Protocol, + EnumCase, + Initializer, + Deinitializer, + InstanceMethod, + TypeMethod, + Operator, + InstanceProperty, + TypeProperty, + InstanceSubscript, + TypeSubscript, + Function, + Variable, + TypeAlias, + AssociatedType, + Macro, + Extension, + Unknown, +}; + +const char* toString(SymbolKind kind); +bool isNominalType(SymbolKind kind); + +enum class AccessLevel { + Private, + FilePrivate, + Internal, + Package, + Public, + Open, + Unknown +}; + +const char* toString(AccessLevel level); + +struct Version { + int major = 0; + int minor = 0; + int patch = 0; +}; + +struct Availability { + // "iOS", "macOS", ..., or "*" for platform-agnostic attributes. + std::string domain; + std::optional introduced; + std::optional deprecated; + std::optional obsoleted; + std::string message; + std::string renamed; + bool isUnconditionallyDeprecated = false; + bool isUnconditionallyUnavailable = false; +}; + +struct GenericParameter { + std::string name; + int depth = 0; + int index = 0; +}; + +struct GenericConstraint { + // "conformance", "superclass" or "sameType". + std::string kind; + std::string lhs; + std::string rhs; + std::string rhsPrecise; +}; + +struct Parameter { + // Empty when the argument is unlabeled (`_`). + std::string label; + std::string internalName; + TypeRef type; + // Ownership/passing modifier in front of the type: "inout", "borrowing", + // "consuming", "sending", or empty. + std::string modifier; + // Type attributes such as "@escaping", "@autoclosure", "@Sendable". + std::vector attributes; + std::string defaultValue; + bool isVariadic = false; +}; + +struct SourceLocation { + std::string uri; + int line = 0; + int character = 0; +}; + +struct SwiftExtensionInfo { + // Module that declares the extended type (e.g. "Swift" for `extension + // String`). + std::string extendedModule; + std::string typeKind; + std::vector constraints; +}; + +struct Relationship { + std::string kind; + std::string source; + std::string target; + std::string targetFallback; + std::string sourceOriginId; + std::string sourceOriginName; +}; + +struct Symbol { + std::string preciseId; + SymbolKind kind = SymbolKind::Unknown; + std::string kindIdentifier; + std::vector pathComponents; + // Last path component as Swift spells it, e.g. "scale(by:)" or "x". + std::string name; + // `name` without the argument-label suffix, e.g. "scale". + std::string baseName; + AccessLevel access = AccessLevel::Unknown; + Fragments declaration; + std::string declarationText; + + // Leading declaration attributes ("@MainActor", "nonisolated", ...). + std::vector attributes; + // Declaration modifiers ("static", "class", "mutating", "override", + // "convenience", "final", "required", ...). + std::vector modifiers; + + // Callables (functions, methods, initializers, subscripts, enum case + // payloads). + std::vector parameters; + std::optional returnType; + bool isAsync = false; + bool isThrowing = false; + bool isRethrowing = false; + TypeRef thrownType; + // `init?` / `init!`. + bool isFailable = false; + bool isImplicitlyUnwrappedFailable = false; + + // Properties, variables and subscripts. + std::optional valueType; + bool isSettable = false; + bool isLet = false; + + // Type aliases. + std::optional aliasedType; + + bool isStatic = false; + bool isSynthesized = false; + bool isProtocolRequirement = false; + bool isOptionalRequirement = false; + + std::vector genericParameters; + std::vector genericConstraints; + std::optional extension; + std::vector availability; + std::vector docComment; + std::optional location; + // Graph file the symbol was read from, relative to the scanned directory. + std::string sourceGraph; + + // Resolved relationships. + std::string parentId; + std::vector memberIds; + std::vector conformances; + std::string superclassId; + std::string overriddenId; + // Requirement or default implementation this member originates from. + std::string sourceOriginId; + std::string sourceOriginName; + std::vector defaultImplementationOf; +}; + +// A type declared outside the module that the module extends +// (e.g. `extension String`). Its members live in Module::symbols. +struct ExternalType { + std::string preciseId; + // Qualified name as reported by the graph, e.g. "Swift.String". + std::string qualifiedName; + std::string extendedModule; + std::string typeKind; + std::vector memberIds; +}; + +struct Platform { + std::string architecture; + std::string vendor; + std::string operatingSystem; + std::string environment; + std::optional minimumVersion; +}; + +struct Module { + std::string name; + Platform platform; + Version formatVersion; + std::string generator; + std::vector graphFiles; + + std::map symbols; + std::map externalTypes; + // Qualified names of declarations outside the module that relationships + // point at (conformances, superclasses, extended types), by USR. + std::map externalNames; + std::vector relationships; + // Declarations without a parent inside the module, in source order. + std::vector topLevelIds; + + const Symbol* find(const std::string& preciseId) const; +}; + +enum class Severity { Warning, Error }; + +struct Diagnostic { + Severity severity = Severity::Warning; + // Stable machine-readable code, e.g. "duplicate-symbol". + std::string code; + std::string message; + std::string file; + std::string symbolId; +}; + +struct ModuleSet { + std::map modules; + std::vector diagnostics; + + bool hasErrors() const; +}; + +// Deterministic JSON rendering of a module's IR, used for snapshots and +// `--swift-ir-output`. +std::string dumpModuleJSON(const Module& module); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SymbolGraphLoader.cpp b/metadata-generator/src/Swift/SymbolGraphLoader.cpp new file mode 100644 index 000000000..e30f08ffb --- /dev/null +++ b/metadata-generator/src/Swift/SymbolGraphLoader.cpp @@ -0,0 +1,1070 @@ +#include "SymbolGraphLoader.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Swift { + +namespace { + +namespace fs = llvm::sys::fs; +namespace path = llvm::sys::path; +using llvm::json::Array; +using llvm::json::Object; + +void report(std::vector& diagnostics, Severity severity, + std::string code, std::string message, std::string file, + std::string symbolId = "") { + diagnostics.push_back(Diagnostic{severity, std::move(code), + std::move(message), std::move(file), + std::move(symbolId)}); +} + +std::string str(const Object* object, llvm::StringRef key) { + if (!object) { + return ""; + } + auto value = object->getString(key); + return value ? value->str() : ""; +} + +int integer(const Object* object, llvm::StringRef key) { + if (!object) { + return 0; + } + auto value = object->getInteger(key); + return value ? static_cast(*value) : 0; +} + +bool boolean(const Object* object, llvm::StringRef key) { + if (!object) { + return false; + } + auto value = object->getBoolean(key); + return value && *value; +} + +std::optional version(const Object* object) { + if (!object) { + return std::nullopt; + } + return Version{integer(object, "major"), integer(object, "minor"), + integer(object, "patch")}; +} + +bool isGraphFileName(llvm::StringRef fileName) { + return fileName.endswith(".symbols.json") || + fileName.endswith(".symbolgraph"); +} + +// --- Declaration fragment parsing ------------------------------------------- +// +// Symbol graphs carry most semantics (effects, settability, labels, failable +// initializers, actor-ness) only inside `declarationFragments`, where +// structural punctuation is mixed into "text" fragments (e.g. "?) -> "). +// Text fragments are therefore split into single structural tokens before +// parsing. + +struct Token { + enum class Type { Fragment, Punct, Space, Word, Arrow }; + Type type; + // Fragment kind for Fragment tokens, "text" otherwise. + std::string kind; + std::string text; + std::string precise; + + bool isPunct(char c) const { + return type == Type::Punct && text.size() == 1 && text[0] == c; + } + bool isFragment(llvm::StringRef fragmentKind) const { + return type == Type::Fragment && kind == fragmentKind; + } + bool isKeyword(llvm::StringRef keyword) const { + return isFragment("keyword") && text == keyword; + } +}; + +using Tokens = std::vector; + +Tokens tokenize(const Fragments& fragments) { + Tokens tokens; + for (const auto& fragment : fragments) { + // Custom attributes (global actors, property wrappers) arrive as an "@" + // fragment followed by the attribute type's name. + if (fragment.kind == "attribute" && !tokens.empty() && + tokens.back().isFragment("attribute") && tokens.back().text == "@") { + tokens.back().text += fragment.spelling; + tokens.back().precise = fragment.preciseIdentifier; + continue; + } + if (fragment.kind != "text") { + tokens.push_back(Token{Token::Type::Fragment, fragment.kind, + fragment.spelling, fragment.preciseIdentifier}); + continue; + } + + llvm::StringRef text = fragment.spelling; + // Attributes with arguments (e.g. "@backDeployed(before: iOS 17.0)\n") are + // emitted as plain text rather than as attribute fragments. + if (text.ltrim().startswith("@")) { + tokens.push_back( + Token{Token::Type::Fragment, "attribute", text.trim().str(), ""}); + continue; + } + + size_t i = 0; + while (i < text.size()) { + char c = text[i]; + if (llvm::isSpace(c)) { + size_t end = i; + while (end < text.size() && llvm::isSpace(text[end])) { + end++; + } + tokens.push_back( + Token{Token::Type::Space, "text", text.slice(i, end).str(), ""}); + i = end; + } else if (text.substr(i).startswith("->")) { + tokens.push_back(Token{Token::Type::Arrow, "text", "->", ""}); + i += 2; + } else if (llvm::StringRef("()[]<>,:?!={}&").contains(c)) { + tokens.push_back( + Token{Token::Type::Punct, "text", std::string(1, c), ""}); + i++; + } else { + size_t end = i; + while (end < text.size() && !llvm::isSpace(text[end]) && + !llvm::StringRef("()[]<>,:?!={}&").contains(text[end]) && + !text.substr(end).startswith("->")) { + end++; + } + tokens.push_back( + Token{Token::Type::Word, "text", text.slice(i, end).str(), ""}); + i = end; + } + } + } + return tokens; +} + +bool opens(const Token& token) { + return token.isPunct('(') || token.isPunct('[') || token.isPunct('<'); +} + +bool closes(const Token& token) { + return token.isPunct(')') || token.isPunct(']') || token.isPunct('>'); +} + +TypeRef makeTypeRef(Tokens::const_iterator begin, Tokens::const_iterator end) { + while (begin != end && begin->type == Token::Type::Space) { + ++begin; + } + while (end != begin && std::prev(end)->type == Token::Type::Space) { + --end; + } + + TypeRef type; + for (auto it = begin; it != end; ++it) { + type.spelling += it->text; + if (it->type == Token::Type::Fragment) { + type.fragments.push_back(Fragment{it->kind, it->text, it->precise}); + } else if (!type.fragments.empty() && + type.fragments.back().kind == "text") { + type.fragments.back().spelling += it->text; + } else { + type.fragments.push_back(Fragment{"text", it->text, ""}); + } + } + return type; +} + +bool isVoid(const TypeRef& type) { + return type.spelling == "()" || type.spelling == "Void"; +} + +class DeclarationParser { + public: + DeclarationParser(const Tokens& tokens, Symbol& symbol) + : _tokens(tokens), _symbol(symbol) {} + + // Returns false when the declaration does not have the expected shape. + bool parse() { + parsePrefix(); + if (_intro.empty()) { + return false; + } + + if (_intro == "init") { + if (peekPunct('?')) { + _symbol.isFailable = true; + _pos++; + } else if (peekPunct('!')) { + _symbol.isFailable = true; + _symbol.isImplicitlyUnwrappedFailable = true; + _pos++; + } + } else if (_intro != "subscript" && _intro != "deinit") { + skipSpaces(); + if (!atEnd() && _tokens[_pos].isFragment("identifier")) { + _pos++; + } + } + + skipSpaces(); + if (peekPunct('<')) { + skipBalanced(); + } + + bool isCallable = _intro == "func" || _intro == "init" || + _intro == "subscript" || _intro == "case" || + _intro == "macro"; + if (isCallable) { + skipSpaces(); + if (peekPunct('(')) { + if (!parseParameterList()) { + return false; + } + } else if (_intro != "case") { + return false; + } + parseEffects(); + skipSpaces(); + if (!atEnd() && _tokens[_pos].type == Token::Type::Arrow) { + _pos++; + size_t start = _pos; + size_t end = findTypeEnd(start); + _symbol.returnType = + makeTypeRef(_tokens.begin() + start, _tokens.begin() + end); + _pos = end; + } + if (_intro == "subscript") { + _symbol.valueType = _symbol.returnType; + parseAccessors(/*storedIfMissing*/ false); + } + return true; + } + + if (_intro == "var" || _intro == "let") { + skipSpaces(); + if (!peekPunct(':')) { + return false; + } + _pos++; + size_t start = _pos; + size_t end = findTypeEnd(start); + _symbol.valueType = + makeTypeRef(_tokens.begin() + start, _tokens.begin() + end); + _pos = end; + _symbol.isLet = _intro == "let"; + parseAccessors(/*storedIfMissing*/ !_symbol.isLet); + return true; + } + + if (_intro == "typealias") { + skipSpaces(); + if (peekPunct('=')) { + _pos++; + size_t start = _pos; + size_t end = findTypeEnd(start); + _symbol.aliasedType = + makeTypeRef(_tokens.begin() + start, _tokens.begin() + end); + } + return true; + } + + return true; + } + + const std::string& intro() const { return _intro; } + bool malformed() const { return _malformed; } + + private: + bool atEnd() const { return _pos >= _tokens.size(); } + + bool peekPunct(char c) const { return !atEnd() && _tokens[_pos].isPunct(c); } + + void skipSpaces() { + while (!atEnd() && _tokens[_pos].type == Token::Type::Space) { + _pos++; + } + } + + void skipBalanced() { + int depth = 0; + while (!atEnd()) { + const Token& token = _tokens[_pos++]; + if (opens(token)) { + depth++; + } else if (closes(token) && --depth == 0) { + return; + } + } + } + + bool isIntroKeyword(const Token& token) const { + static const std::set intros = { + "func", "init", "deinit", "subscript", "case", + "var", "let", "typealias", "associatedtype", "struct", + "enum", "protocol", "actor", "extension", "macro"}; + if (!token.isFragment("keyword")) { + return false; + } + if (token.text == "class") { + // `class func` / `class var` use `class` as a modifier. + return _symbol.kind == SymbolKind::Class || + _symbol.kind == SymbolKind::Actor; + } + return intros.count(token.text) > 0; + } + + void parsePrefix() { + while (!atEnd()) { + const Token& token = _tokens[_pos]; + if (token.isFragment("attribute")) { + _symbol.attributes.push_back(llvm::StringRef(token.text).trim().str()); + } else if (isIntroKeyword(token)) { + _intro = token.text; + _pos++; + return; + } else if (token.isFragment("keyword")) { + _symbol.modifiers.push_back(token.text); + } else if (token.type != Token::Type::Space) { + return; + } + _pos++; + } + } + + // End of a type that starts at `start`: the first `where`, `{`, or `=` at + // nesting depth zero, or the end of the declaration. + size_t findTypeEnd(size_t start) const { + int depth = 0; + for (size_t i = start; i < _tokens.size(); i++) { + const Token& token = _tokens[i]; + if (opens(token)) { + depth++; + } else if (closes(token)) { + depth--; + } else if (depth == 0 && (token.isKeyword("where") || + token.isPunct('{') || token.isPunct('='))) { + return i; + } + } + return _tokens.size(); + } + + bool parseParameterList() { + _pos++; // '(' + std::vector> segments; + size_t segmentStart = _pos; + int depth = 0; + while (!atEnd()) { + const Token& token = _tokens[_pos]; + if (depth == 0 && (token.isPunct(',') || token.isPunct(')'))) { + segments.emplace_back(segmentStart, _pos); + segmentStart = _pos + 1; + if (token.isPunct(')')) { + _pos++; + for (const auto& segment : segments) { + parseParameter(segment.first, segment.second); + } + return true; + } + } else if (opens(token)) { + depth++; + } else if (closes(token)) { + depth--; + } + _pos++; + } + return false; + } + + void parseParameter(size_t begin, size_t end) { + while (begin < end && _tokens[begin].type == Token::Type::Space) { + begin++; + } + if (begin == end) { + return; + } + + Parameter parameter; + bool hasExternal = false; + if (_tokens[begin].isFragment("externalParam")) { + hasExternal = true; + parameter.label = _tokens[begin].text == "_" ? "" : _tokens[begin].text; + parameter.internalName = parameter.label; + begin++; + } + while (begin < end && _tokens[begin].type == Token::Type::Space) { + begin++; + } + if (begin < end && _tokens[begin].isFragment("internalParam")) { + parameter.internalName = _tokens[begin].text; + begin++; + } + while (begin < end && _tokens[begin].type == Token::Type::Space) { + begin++; + } + if (begin < end && _tokens[begin].isPunct(':')) { + begin++; + } else if (hasExternal) { + // An externalParam must be followed by a type annotation. + _malformed = true; + } + + // Default value: everything after a depth-zero '='. + size_t typeEnd = end; + int depth = 0; + for (size_t i = begin; i < end; i++) { + if (opens(_tokens[i])) { + depth++; + } else if (closes(_tokens[i])) { + depth--; + } else if (depth == 0 && _tokens[i].isPunct('=')) { + typeEnd = i; + parameter.defaultValue = + makeTypeRef(_tokens.begin() + i + 1, _tokens.begin() + end) + .spelling; + break; + } + } + + static const std::set modifiers = { + "inout", "borrowing", "consuming", "sending", "__owned", "__shared"}; + while (begin < typeEnd) { + const Token& token = _tokens[begin]; + if (token.type == Token::Type::Space) { + begin++; + } else if (token.isFragment("attribute")) { + parameter.attributes.push_back( + llvm::StringRef(token.text).trim().str()); + begin++; + } else if (token.isFragment("keyword") && modifiers.count(token.text)) { + parameter.modifier = token.text; + begin++; + } else { + break; + } + } + + size_t last = typeEnd; + while (last > begin && _tokens[last - 1].type == Token::Type::Space) { + last--; + } + if (last > begin && _tokens[last - 1].type == Token::Type::Word && + _tokens[last - 1].text == "...") { + parameter.isVariadic = true; + last--; + } + + parameter.type = + makeTypeRef(_tokens.begin() + begin, _tokens.begin() + last); + _symbol.parameters.push_back(std::move(parameter)); + } + + void parseEffects() { + while (true) { + skipSpaces(); + if (atEnd()) { + return; + } + const Token& token = _tokens[_pos]; + if (token.isKeyword("async") || token.isKeyword("reasync")) { + _symbol.isAsync = true; + _pos++; + } else if (token.isKeyword("throws")) { + _symbol.isThrowing = true; + _pos++; + if (peekPunct('(')) { + size_t start = _pos + 1; + skipBalanced(); + _symbol.thrownType = + makeTypeRef(_tokens.begin() + start, _tokens.begin() + _pos - 1); + } + } else if (token.isKeyword("rethrows")) { + _symbol.isThrowing = true; + _symbol.isRethrowing = true; + _pos++; + } else { + return; + } + } + } + + // `{ get }`, `{ get set }`, or no accessor block. A `var` without an + // accessor block is stored and therefore settable. + void parseAccessors(bool storedIfMissing) { + skipSpaces(); + if (!peekPunct('{')) { + _symbol.isSettable = storedIfMissing; + return; + } + while (!atEnd() && !_tokens[_pos].isPunct('}')) { + if (_tokens[_pos].isKeyword("set")) { + _symbol.isSettable = true; + } + _pos++; + } + } + + const Tokens& _tokens; + Symbol& _symbol; + size_t _pos = 0; + std::string _intro; + bool _malformed = false; +}; + +// "scale(by:)" -> {"by"}, "describe(_:)" -> {""}, "x" -> none. +std::optional> labelsFromName(llvm::StringRef name) { + size_t open = name.find('('); + if (open == llvm::StringRef::npos || !name.endswith(")")) { + return std::nullopt; + } + llvm::StringRef inner = name.slice(open + 1, name.size() - 1); + std::vector labels; + while (!inner.empty()) { + auto split = inner.split(':'); + labels.push_back(split.first == "_" ? "" : split.first.str()); + inner = split.second; + } + return labels; +} + +SymbolKind kindFromIdentifier(llvm::StringRef identifier) { + return llvm::StringSwitch(identifier) + .Case("swift.class", SymbolKind::Class) + .Case("swift.struct", SymbolKind::Struct) + .Case("swift.enum", SymbolKind::Enum) + .Case("swift.protocol", SymbolKind::Protocol) + .Case("swift.enum.case", SymbolKind::EnumCase) + .Case("swift.init", SymbolKind::Initializer) + .Case("swift.deinit", SymbolKind::Deinitializer) + .Case("swift.method", SymbolKind::InstanceMethod) + .Case("swift.type.method", SymbolKind::TypeMethod) + .Case("swift.func.op", SymbolKind::Operator) + .Case("swift.property", SymbolKind::InstanceProperty) + .Case("swift.type.property", SymbolKind::TypeProperty) + .Case("swift.subscript", SymbolKind::InstanceSubscript) + .Case("swift.type.subscript", SymbolKind::TypeSubscript) + .Case("swift.func", SymbolKind::Function) + .Case("swift.var", SymbolKind::Variable) + .Case("swift.typealias", SymbolKind::TypeAlias) + .Case("swift.associatedtype", SymbolKind::AssociatedType) + .Case("swift.macro", SymbolKind::Macro) + .Case("swift.extension", SymbolKind::Extension) + .Default(SymbolKind::Unknown); +} + +AccessLevel accessFromString(llvm::StringRef access) { + return llvm::StringSwitch(access) + .Case("private", AccessLevel::Private) + .Case("fileprivate", AccessLevel::FilePrivate) + .Case("internal", AccessLevel::Internal) + .Case("package", AccessLevel::Package) + .Case("public", AccessLevel::Public) + .Case("open", AccessLevel::Open) + .Default(AccessLevel::Unknown); +} + +Fragments parseFragments(const Array* array) { + Fragments fragments; + if (!array) { + return fragments; + } + for (const auto& value : *array) { + const Object* object = value.getAsObject(); + if (!object) { + continue; + } + fragments.push_back(Fragment{str(object, "kind"), str(object, "spelling"), + str(object, "preciseIdentifier")}); + } + return fragments; +} + +std::vector parseConstraints(const Array* array) { + std::vector constraints; + if (!array) { + return constraints; + } + for (const auto& value : *array) { + const Object* object = value.getAsObject(); + if (!object) { + continue; + } + constraints.push_back( + GenericConstraint{str(object, "kind"), str(object, "lhs"), + str(object, "rhs"), str(object, "rhsPrecise")}); + } + return constraints; +} + +void parseAvailability(const Array* array, Symbol& symbol) { + if (!array) { + return; + } + for (const auto& value : *array) { + const Object* object = value.getAsObject(); + if (!object) { + continue; + } + Availability availability; + availability.domain = str(object, "domain"); + availability.introduced = version(object->getObject("introduced")); + availability.deprecated = version(object->getObject("deprecated")); + availability.obsoleted = version(object->getObject("obsoleted")); + availability.message = str(object, "message"); + availability.renamed = str(object, "renamed"); + availability.isUnconditionallyDeprecated = + boolean(object, "isUnconditionallyDeprecated"); + availability.isUnconditionallyUnavailable = + boolean(object, "isUnconditionallyUnavailable"); + symbol.availability.push_back(std::move(availability)); + } +} + +std::optional parseSymbol(const Object& object, + const std::string& graphName, + std::vector& diagnostics) { + Symbol symbol; + symbol.preciseId = str(object.getObject("identifier"), "precise"); + if (symbol.preciseId.empty()) { + report(diagnostics, Severity::Warning, "missing-field", + "symbol without identifier.precise skipped", graphName); + return std::nullopt; + } + + symbol.kindIdentifier = str(object.getObject("kind"), "identifier"); + symbol.kind = kindFromIdentifier(symbol.kindIdentifier); + if (symbol.kind == SymbolKind::Unknown) { + report(diagnostics, Severity::Warning, "unknown-symbol-kind", + "unrecognized symbol kind '" + symbol.kindIdentifier + "'", + graphName, symbol.preciseId); + } + + if (const Array* components = object.getArray("pathComponents")) { + for (const auto& component : *components) { + if (auto value = component.getAsString()) { + symbol.pathComponents.push_back(value->str()); + } + } + } + symbol.name = symbol.pathComponents.empty() + ? str(object.getObject("names"), "title") + : symbol.pathComponents.back(); + symbol.baseName = llvm::StringRef(symbol.name).split('(').first.str(); + symbol.access = accessFromString(str(&object, "accessLevel")); + symbol.isSynthesized = + llvm::StringRef(symbol.preciseId).contains("::SYNTHESIZED::"); + symbol.sourceGraph = graphName; + + symbol.declaration = parseFragments(object.getArray("declarationFragments")); + for (const auto& fragment : symbol.declaration) { + symbol.declarationText += fragment.spelling; + } + + if (const Object* generics = object.getObject("swiftGenerics")) { + if (const Array* parameters = generics->getArray("parameters")) { + for (const auto& value : *parameters) { + if (const Object* parameter = value.getAsObject()) { + symbol.genericParameters.push_back(GenericParameter{ + str(parameter, "name"), integer(parameter, "depth"), + integer(parameter, "index")}); + } + } + } + symbol.genericConstraints = + parseConstraints(generics->getArray("constraints")); + } + + if (const Object* extension = object.getObject("swiftExtension")) { + symbol.extension = SwiftExtensionInfo{ + str(extension, "extendedModule"), str(extension, "typeKind"), + parseConstraints(extension->getArray("constraints"))}; + } + + parseAvailability(object.getArray("availability"), symbol); + + if (const Object* doc = object.getObject("docComment")) { + if (const Array* lines = doc->getArray("lines")) { + for (const auto& line : *lines) { + symbol.docComment.push_back(str(line.getAsObject(), "text")); + } + } + } + + if (const Object* location = object.getObject("location")) { + const Object* position = location->getObject("position"); + symbol.location = + SourceLocation{str(location, "uri"), integer(position, "line"), + integer(position, "character")}; + } + + Tokens tokens = tokenize(symbol.declaration); + DeclarationParser parser(tokens, symbol); + bool parsed = parser.parse(); + if (parser.intro() == "actor") { + symbol.kind = SymbolKind::Actor; + } + if (!parsed || parser.malformed()) { + report(diagnostics, Severity::Warning, "unparsed-declaration", + "could not parse declaration '" + symbol.declarationText + "'", + graphName, symbol.preciseId); + } + + // The functionSignature return is cleaner than the declaration tail (no + // trailing where-clause) and is present for every function-like symbol. + if (const Object* signature = object.getObject("functionSignature")) { + if (const Array* returns = signature->getArray("returns")) { + Fragments fragments = parseFragments(returns); + Tokens returnTokens = tokenize(fragments); + TypeRef type = makeTypeRef(returnTokens.begin(), returnTokens.end()); + if (isVoid(type) || type.empty()) { + symbol.returnType.reset(); + } else { + symbol.returnType = type; + } + } + } + if (symbol.returnType && isVoid(*symbol.returnType)) { + symbol.returnType.reset(); + } + if (symbol.kind == SymbolKind::InstanceSubscript || + symbol.kind == SymbolKind::TypeSubscript) { + symbol.valueType = symbol.returnType; + } + + if (auto labels = labelsFromName(symbol.name)) { + bool matches = labels->size() == symbol.parameters.size(); + for (size_t i = 0; matches && i < labels->size(); i++) { + matches = (*labels)[i] == symbol.parameters[i].label; + } + if (!matches) { + report(diagnostics, Severity::Warning, "parameter-label-mismatch", + "parsed parameters of '" + symbol.declarationText + + "' do not match the symbol name '" + symbol.name + "'", + graphName, symbol.preciseId); + } + } + + switch (symbol.kind) { + case SymbolKind::TypeMethod: + case SymbolKind::TypeProperty: + case SymbolKind::TypeSubscript: + symbol.isStatic = true; + break; + case SymbolKind::Operator: + symbol.isStatic = std::count(symbol.modifiers.begin(), + symbol.modifiers.end(), "static") > 0; + break; + default: + break; + } + + return symbol; +} + +// Members and top-level declarations are listed in source order; synthesized +// symbols have no location and follow, ordered by USR. +void sortBySourceOrder(std::vector& ids, const Module& module) { + auto key = [&](const std::string& id) { + const Symbol* symbol = module.find(id); + if (!symbol || !symbol->location) { + return std::make_tuple(1, std::string(), 0, 0, id); + } + return std::make_tuple(0, symbol->location->uri, symbol->location->line, + symbol->location->character, id); + }; + std::sort(ids.begin(), ids.end(), + [&](const std::string& a, const std::string& b) { + return key(a) < key(b); + }); + ids.erase(std::unique(ids.begin(), ids.end()), ids.end()); +} + +void resolve(Module& module, std::vector& diagnostics) { + std::sort(module.relationships.begin(), module.relationships.end(), + [](const Relationship& a, const Relationship& b) { + return std::tie(a.kind, a.source, a.target) < + std::tie(b.kind, b.source, b.target); + }); + module.relationships.erase( + std::unique(module.relationships.begin(), module.relationships.end(), + [](const Relationship& a, const Relationship& b) { + return std::tie(a.kind, a.source, a.target) == + std::tie(b.kind, b.source, b.target); + }), + module.relationships.end()); + + auto rememberExternal = [&](const Relationship& relationship) { + if (!module.find(relationship.target)) { + module.externalNames[relationship.target] = + relationship.targetFallback.empty() ? relationship.target + : relationship.targetFallback; + } + }; + + for (const auto& relationship : module.relationships) { + auto sourceIt = module.symbols.find(relationship.source); + if (sourceIt == module.symbols.end()) { + report(diagnostics, Severity::Warning, "dangling-relationship", + relationship.kind + " relationship from unknown symbol '" + + relationship.source + "'", + module.name, relationship.source); + continue; + } + Symbol& source = sourceIt->second; + const std::string& kind = relationship.kind; + + if (kind == "memberOf" || kind == "requirementOf" || + kind == "optionalRequirementOf") { + source.parentId = relationship.target; + if (!relationship.sourceOriginId.empty()) { + source.sourceOriginId = relationship.sourceOriginId; + source.sourceOriginName = relationship.sourceOriginName; + } + if (kind != "memberOf") { + source.isProtocolRequirement = true; + source.isOptionalRequirement = kind == "optionalRequirementOf"; + } + + auto targetIt = module.symbols.find(relationship.target); + if (targetIt != module.symbols.end()) { + targetIt->second.memberIds.push_back(source.preciseId); + continue; + } + rememberExternal(relationship); + ExternalType& external = module.externalTypes[relationship.target]; + external.preciseId = relationship.target; + external.qualifiedName = module.externalNames[relationship.target]; + if (source.extension) { + external.extendedModule = source.extension->extendedModule; + external.typeKind = source.extension->typeKind; + } + external.memberIds.push_back(source.preciseId); + } else if (kind == "conformsTo") { + source.conformances.push_back(relationship.target); + rememberExternal(relationship); + } else if (kind == "inheritsFrom") { + if (source.kind == SymbolKind::Protocol) { + source.conformances.push_back(relationship.target); + } else { + source.superclassId = relationship.target; + } + rememberExternal(relationship); + } else if (kind == "overrides") { + source.overriddenId = relationship.target; + rememberExternal(relationship); + } else if (kind == "defaultImplementationOf") { + source.defaultImplementationOf.push_back(relationship.target); + rememberExternal(relationship); + } + } + + for (auto& entry : module.symbols) { + Symbol& symbol = entry.second; + sortBySourceOrder(symbol.memberIds, module); + std::sort(symbol.conformances.begin(), symbol.conformances.end()); + symbol.conformances.erase( + std::unique(symbol.conformances.begin(), symbol.conformances.end()), + symbol.conformances.end()); + std::sort(symbol.defaultImplementationOf.begin(), + symbol.defaultImplementationOf.end()); + if (symbol.parentId.empty()) { + module.topLevelIds.push_back(symbol.preciseId); + } + } + for (auto& entry : module.externalTypes) { + sortBySourceOrder(entry.second.memberIds, module); + } + sortBySourceOrder(module.topLevelIds, module); + std::sort(module.graphFiles.begin(), module.graphFiles.end()); +} + +} // namespace + +std::vector SymbolGraphLoader::findGraphFiles( + const std::string& directory, std::vector& diagnostics) { + std::vector files; + if (!fs::is_directory(directory)) { + report(diagnostics, Severity::Error, "missing-directory", + "symbol graph directory does not exist", directory); + return files; + } + + std::error_code ec; + for (fs::recursive_directory_iterator it(directory, ec), end; + it != end && !ec; it.increment(ec)) { + if (it->type() != fs::file_type::regular_file) { + continue; + } + if (isGraphFileName(path::filename(it->path()))) { + files.push_back(it->path()); + } + } + if (ec) { + report(diagnostics, Severity::Error, "unreadable-directory", ec.message(), + directory); + } + std::sort(files.begin(), files.end()); + return files; +} + +void SymbolGraphLoader::addFile(const std::string& filePath, + const std::string& displayName) { + auto buffer = llvm::MemoryBuffer::getFile(filePath); + if (!buffer) { + report(_diagnostics, Severity::Error, "unreadable-file", + buffer.getError().message(), displayName); + return; + } + addBuffer((*buffer)->getBuffer(), displayName); +} + +void SymbolGraphLoader::addBuffer(llvm::StringRef json, + const std::string& displayName) { + auto parsed = llvm::json::parse(json); + if (!parsed) { + report(_diagnostics, Severity::Error, "invalid-json", + llvm::toString(parsed.takeError()), displayName); + return; + } + const Object* root = parsed->getAsObject(); + if (!root) { + report(_diagnostics, Severity::Error, "invalid-json", + "symbol graph root is not an object", displayName); + return; + } + + const Object* metadata = root->getObject("metadata"); + auto format = + version(metadata ? metadata->getObject("formatVersion") : nullptr); + if (!format) { + report(_diagnostics, Severity::Error, "missing-field", + "metadata.formatVersion is missing", displayName); + return; + } + if (format->major != kSupportedFormatMajor) { + report(_diagnostics, Severity::Error, "unsupported-format-version", + "symbol graph format " + std::to_string(format->major) + "." + + std::to_string(format->minor) + " is not supported", + displayName); + return; + } + if (format->minor > kNewestKnownFormatMinor) { + report(_diagnostics, Severity::Warning, "newer-format-version", + "symbol graph format 0." + std::to_string(format->minor) + + " is newer than the newest validated format 0." + + std::to_string(kNewestKnownFormatMinor), + displayName); + } + + const Object* moduleObject = root->getObject("module"); + std::string moduleName = str(moduleObject, "name"); + if (moduleName.empty()) { + report(_diagnostics, Severity::Error, "missing-field", + "module.name is missing", displayName); + return; + } + + Module& module = _modules[moduleName]; + if (module.name.empty()) { + module.name = moduleName; + module.formatVersion = *format; + module.generator = str(metadata, "generator"); + if (const Object* platform = moduleObject->getObject("platform")) { + module.platform.architecture = str(platform, "architecture"); + module.platform.vendor = str(platform, "vendor"); + module.platform.environment = str(platform, "environment"); + if (const Object* os = platform->getObject("operatingSystem")) { + module.platform.operatingSystem = str(os, "name"); + module.platform.minimumVersion = + version(os->getObject("minimumVersion")); + } + } + } else if (std::tie(module.formatVersion.major, module.formatVersion.minor) != + std::tie(format->major, format->minor)) { + report(_diagnostics, Severity::Warning, "mixed-format-versions", + "graph files of module '" + moduleName + + "' use different format versions", + displayName); + } + module.graphFiles.push_back(displayName); + + if (const Array* symbols = root->getArray("symbols")) { + for (const auto& value : *symbols) { + const Object* object = value.getAsObject(); + if (!object) { + continue; + } + auto symbol = parseSymbol(*object, displayName, _diagnostics); + if (!symbol) { + continue; + } + auto existing = module.symbols.find(symbol->preciseId); + if (existing != module.symbols.end()) { + if (existing->second.declarationText != symbol->declarationText) { + report(_diagnostics, Severity::Warning, "duplicate-symbol", + "symbol declared differently in '" + + existing->second.sourceGraph + "' and '" + displayName + + "'; keeping the first", + displayName, symbol->preciseId); + } + continue; + } + std::string id = symbol->preciseId; + module.symbols.emplace(std::move(id), std::move(*symbol)); + } + } + + if (const Array* relationships = root->getArray("relationships")) { + for (const auto& value : *relationships) { + const Object* object = value.getAsObject(); + if (!object) { + continue; + } + const Object* origin = object->getObject("sourceOrigin"); + module.relationships.push_back( + Relationship{str(object, "kind"), str(object, "source"), + str(object, "target"), str(object, "targetFallback"), + str(origin, "identifier"), str(origin, "displayName")}); + } + } +} + +ModuleSet SymbolGraphLoader::finish() { + ModuleSet result; + for (auto& entry : _modules) { + resolve(entry.second, _diagnostics); + } + result.modules = std::move(_modules); + result.diagnostics = std::move(_diagnostics); + return result; +} + +ModuleSet loadSymbolGraphDirectory(const std::string& directory) { + std::vector diagnostics; + auto files = SymbolGraphLoader::findGraphFiles(directory, diagnostics); + + SymbolGraphLoader loader; + for (const auto& file : files) { + llvm::StringRef relative = file; + relative.consume_front(directory); + relative = relative.ltrim('/'); + loader.addFile(file, relative.str()); + } + ModuleSet result = loader.finish(); + result.diagnostics.insert(result.diagnostics.begin(), diagnostics.begin(), + diagnostics.end()); + return result; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SymbolGraphLoader.h b/metadata-generator/src/Swift/SymbolGraphLoader.h new file mode 100644 index 000000000..5058cb28b --- /dev/null +++ b/metadata-generator/src/Swift/SymbolGraphLoader.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include +#include + +#include "SwiftIR.h" + +namespace Swift { + +// Reads Swift symbol graph files (`swiftc -emit-symbol-graph` / +// `swift symbolgraph-extract`) into the Swift IR. +// +// A module's declarations can span several graph files: `M.symbols.json` +// holds M's own declarations, `M@Other.symbols.json` holds M's extensions of +// types declared in module Other. Files are grouped by the module name inside +// the graph, not by file name. +class SymbolGraphLoader { + public: + // Newest symbol graph format this loader has been validated against. + // Newer minor versions load with a warning; other major versions are + // rejected. + static constexpr int kSupportedFormatMajor = 0; + static constexpr int kNewestKnownFormatMinor = 6; + + // Graph files under `directory` (recursive), sorted for deterministic + // loading. + static std::vector findGraphFiles( + const std::string& directory, std::vector& diagnostics); + + void addFile(const std::string& path, const std::string& displayName); + void addBuffer(llvm::StringRef json, const std::string& displayName); + + // Resolves relationships across all added graphs. The loader is spent + // afterwards. + ModuleSet finish(); + + private: + std::map _modules; + std::vector _diagnostics; +}; + +// Convenience: find, load and resolve every graph under `directory`. +ModuleSet loadSymbolGraphDirectory(const std::string& directory); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SymbolGraphParser.cpp b/metadata-generator/src/Swift/SymbolGraphParser.cpp deleted file mode 100644 index 39f36f2df..000000000 --- a/metadata-generator/src/Swift/SymbolGraphParser.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "SymbolGraphParser.h" - -#include -#include -#include -#include - -#include "Meta/MetaEntities.h" -#include "Meta/TypeFactory.h" - -#include -#include -namespace fs = llvm::sys::fs; -namespace path = llvm::sys::path; - -namespace Swift { - -static bool hasSymbolGraphExt(llvm::StringRef filePath) { - auto ext = path::extension(filePath); - return ext == ".symbolgraph" || ext == ".json" || ext == ".symbols"; // allow *.symbols.json -} - -ModuleGraphs SymbolGraphParser::scanDirectory(const std::string& dirPath) { - ModuleGraphs result; - std::error_code ec; - if (!fs::exists(dirPath, ec)) { - return result; - } - - std::regex moduleHint("([A-Za-z0-9_]+)\\.symbols?\\.json$|([A-Za-z0-9_]+)\\.symbolgraph$"); - - for (fs::recursive_directory_iterator it(dirPath, ec), end; it != end && !ec; it.increment(ec)) { - if (ec) break; - if (it->type() != fs::file_type::regular_file) continue; - auto p = it->path(); - if (!hasSymbolGraphExt(p)) continue; - - std::smatch m; - std::string filename = std::string(path::filename(p)); - std::string module; - if (std::regex_search(filename, m, moduleHint)) { - if (m[1].matched) module = m[1].str(); - else if (m[2].matched) module = m[2].str(); - } - if (module.empty()) { - module = std::string(path::filename(path::parent_path(p))); - } - result.filesByModule[module].push_back(std::string(p)); - } - return result; -} - -// Extremely lightweight JSON helpers (only what we need for skeleton) -static std::string findString(const std::string& json, const std::string& key) { - // naive: "key":"value" - auto k = std::string("\"") + key + "\""; - auto pos = json.find(k); - if (pos == std::string::npos) return ""; - pos = json.find(':', pos); - if (pos == std::string::npos) return ""; - pos = json.find('"', pos); - if (pos == std::string::npos) return ""; - auto end = json.find('"', pos + 1); - if (end == std::string::npos) return ""; - return json.substr(pos + 1, end - pos - 1); -} - -static bool contains(const std::string& hay, const std::string& needle) { - return hay.find(needle) != std::string::npos; -} - -std::vector SymbolGraphParser::parseModule(const std::string& moduleName, - const std::vector& graphFiles) { - using namespace Meta; - std::vector metas; - metas.reserve(128); - - // For the skeleton: detect a few simple symbol kinds and emit placeholder metas. - for (const auto& f : graphFiles) { - std::ifstream in(f); - if (!in.good()) continue; - std::stringstream buffer; buffer << in.rdbuf(); - auto json = buffer.str(); - - // naive scan for "symbol" entries and pick a few kinds - // e.g., "kind": { "identifier": "swift.class" }, name, module, etc. - // We'll create InterfaceMeta for class, StructMeta for struct, EnumMeta for enum. - - // This is a placeholder approach; a complete parser should iterate the JSON arrays. - // We’ll just search by snippets to bootstrap. - if (contains(json, "swift.class")) { - auto name = findString(json, "title"); - auto* iface = new InterfaceMeta(); - iface->name = name.empty() ? "SwiftClass" : name; - iface->jsName = iface->name; - metas.push_back(iface); - } - if (contains(json, "swift.struct")) { - auto name = findString(json, "title"); - auto* st = new StructMeta(); - st->name = name.empty() ? "SwiftStruct" : name; - st->jsName = st->name; - metas.push_back(st); - } - if (contains(json, "swift.enum")) { - auto name = findString(json, "title"); - auto* en = new EnumMeta(); - en->name = name.empty() ? "SwiftEnum" : name; - en->jsName = en->name; - metas.push_back(en); - } - if (contains(json, "swift.protocol")) { - auto name = findString(json, "title"); - auto* pr = new ProtocolMeta(); - pr->name = name.empty() ? "SwiftProtocol" : name; - pr->jsName = pr->name; - metas.push_back(pr); - } - } - - // de-dup very naively by jsName - std::unordered_map byName; - std::vector unique; - for (auto* m : metas) { - if (!m) continue; - if (!byName.count(m->jsName)) { - byName[m->jsName] = m; - unique.push_back(m); - } else { - delete m; // drop duplicates in bootstrap - } - } - return unique; -} - -} // namespace Swift diff --git a/metadata-generator/src/Swift/SymbolGraphParser.h b/metadata-generator/src/Swift/SymbolGraphParser.h deleted file mode 100644 index 4ccd53f35..000000000 --- a/metadata-generator/src/Swift/SymbolGraphParser.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace Meta { class Meta; } - -namespace Swift { -struct ModuleGraphs { - // Module name -> list of file paths (*.symbolgraph and/or *.symbols.json) - std::unordered_map> filesByModule; -}; - -// Minimal Swift symbolgraph -> Meta bridge -class SymbolGraphParser { -public: - // Scan a directory for *.symbolgraph or *.symbols.json and group by module - static ModuleGraphs scanDirectory(const std::string& dirPath); - - // Parse all symbol graph files for a module into Meta objects - static std::vector parseModule(const std::string& moduleName, - const std::vector& graphFiles); -}; -} diff --git a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp index c2f680bb1..1c7c11453 100644 --- a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp +++ b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp @@ -1,55 +1,27 @@ #include "SwiftDefinitionWriter.h" -#include "Meta/MetaEntities.h" +#include namespace TypeScript { -using namespace Meta; std::string SwiftDefinitionWriter::write() { - // Header - _buffer << "// Generated from Swift Symbol Graphs\n"; - _buffer << "// Module: " << _module.first << "\n\n"; - - for (auto *m : _module.second) { - if (m) m->visit(this); + std::ostringstream out; + out << "// Generated from Swift symbol graphs for module " << _module.name + << ".\n"; + out << "// Type-only: no Swift members are callable from JavaScript yet.\n\n"; + + for (const auto& id : _module.topLevelIds) { + const Swift::Symbol* symbol = _module.find(id); + if (!symbol || !Swift::isNominalType(symbol->kind)) { + continue; } - - return _buffer.str(); -} - -void SwiftDefinitionWriter::visit(InterfaceMeta* meta) { - _buffer << "declare class " << meta->jsName << " { }\n"; -} - -void SwiftDefinitionWriter::visit(ProtocolMeta* meta) { - _buffer << "interface " << meta->jsName << " { }\n"; -} - -void SwiftDefinitionWriter::visit(CategoryMeta* /*meta*/) {} - -void SwiftDefinitionWriter::visit(FunctionMeta* meta) { - _buffer << "declare function " << meta->jsName << "(...args: any[]): any;\n"; -} - -void SwiftDefinitionWriter::visit(StructMeta* meta) { - _buffer << "interface " << meta->jsName << " { }\n"; - _buffer << "declare var " << meta->jsName << ": interop.StructType<" << meta->jsName << ">;\n"; -} - -void SwiftDefinitionWriter::visit(UnionMeta* meta) { - _buffer << "interface " << meta->jsName << " { }\n"; -} - -void SwiftDefinitionWriter::visit(EnumMeta* meta) { - _buffer << "declare const enum " << meta->jsName << " { }\n"; -} - -void SwiftDefinitionWriter::visit(VarMeta* meta) { - _buffer << "declare var " << meta->jsName << ": any;\n"; + if (symbol->kind == Swift::SymbolKind::Protocol) { + out << "interface " << symbol->name << " {}\n"; + } else { + out << "declare class " << symbol->name << " {}\n"; + } + } + return out.str(); } -void SwiftDefinitionWriter::visit(MethodMeta* /*meta*/) {} -void SwiftDefinitionWriter::visit(PropertyMeta* /*meta*/) {} -void SwiftDefinitionWriter::visit(EnumConstantMeta* /*meta*/) {} - -} // namespace TypeScript +} // namespace TypeScript diff --git a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h index aa7679418..97eb59403 100644 --- a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h +++ b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h @@ -1,38 +1,23 @@ #pragma once -#include "DocSetManager.h" -#include "Meta/MetaEntities.h" -#include #include -#include -#include -#include + +#include "Swift/SwiftIR.h" namespace TypeScript { -class SwiftDefinitionWriter : Meta::MetaVisitor { -public: - SwiftDefinitionWriter(std::pair> &module, - std::string docSetPath) - : _module(module), _docSet(docSetPath) {} - std::string write(); +// Writes `swift!.d.ts`. Declarations are type-only: they name the +// module's Swift types, but no Swift member is callable from JavaScript, so +// none is declared. +class SwiftDefinitionWriter { + public: + explicit SwiftDefinitionWriter(const Swift::Module& module) + : _module(module) {} - // MetaVisitor - void visit(Meta::InterfaceMeta* meta) override; - void visit(Meta::ProtocolMeta* meta) override; - void visit(Meta::CategoryMeta* meta) override; - void visit(Meta::FunctionMeta* meta) override; - void visit(Meta::StructMeta* meta) override; - void visit(Meta::UnionMeta* meta) override; - void visit(Meta::EnumMeta* meta) override; - void visit(Meta::VarMeta* meta) override; - void visit(Meta::MethodMeta* meta) override; - void visit(Meta::PropertyMeta* meta) override; - void visit(Meta::EnumConstantMeta* meta) override; + std::string write(); -private: - std::pair> &_module; // moduleName, metas - DocSetManager _docSet; - std::ostringstream _buffer; + private: + const Swift::Module& _module; }; -} + +} // namespace TypeScript diff --git a/metadata-generator/src/main.cpp b/metadata-generator/src/main.cpp index 6b9f45854..df30e572c 100644 --- a/metadata-generator/src/main.cpp +++ b/metadata-generator/src/main.cpp @@ -1,3 +1,14 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + #include "Binary/binarySerializer.h" #include "HeadersParser/Parser.h" #include "Meta/DeclarationConverterVisitor.h" @@ -7,20 +18,11 @@ #include "Meta/Filters/ModulesBlacklist.h" #include "Meta/Filters/RemoveDuplicateMembersFilter.h" #include "Meta/Filters/ResolveGlobalNamesCollisionsFilter.h" +#include "Swift/SymbolGraphLoader.h" #include "TypeScript/DefinitionWriter.h" #include "TypeScript/DocSetManager.h" -#include "Yaml/YamlSerializer.h" -#include "Swift/SymbolGraphParser.h" #include "TypeScript/SwiftDefinitionWriter.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Yaml/YamlSerializer.h" // Command line parameters llvm::cl::opt cla_verbose("verbose", llvm::cl::desc("Set verbose output mode"), llvm::cl::value_desc("bool")); @@ -41,6 +43,11 @@ llvm::cl::list cla_clangArguments(llvm::cl::ConsumeAfter, llvm::cl::desc // Swift support llvm::cl::opt cla_swiftSymbolGraphDir("swift-symbolgraph-dir", llvm::cl::desc("Directory containing Swift .symbolgraph files to import"), llvm::cl::value_desc("")); llvm::cl::opt cla_skipObjC("skip-objc", llvm::cl::desc("Skip Objective-C parsing and only run Swift symbolgraph import"), llvm::cl::init(false)); +llvm::cl::opt cla_swiftIROutputDir( + "swift-ir-output", + llvm::cl::desc("Directory to write the Swift IR (.swift-ir.json) " + "for each imported module"), + llvm::cl::value_desc("")); class MetaGenerationConsumer : public clang::ASTConsumer { public: @@ -241,38 +248,61 @@ int main(int argc, const char** argv) } // Swift: read symbol graphs and emit TS - if (!cla_outputDtsFolder.empty() && !cla_swiftSymbolGraphDir.empty()) { - auto graphs = Swift::SymbolGraphParser::scanDirectory(cla_swiftSymbolGraphDir); - llvm::sys::fs::create_directories(cla_outputDtsFolder); - std::string docSetPath = cla_docSetFile.empty() ? "" : cla_docSetFile.getValue(); - for (auto &entry : graphs.filesByModule) { - const auto &moduleName = entry.first; - const auto &files = entry.second; - auto metas = Swift::SymbolGraphParser::parseModule(moduleName, files); - std::pair> swiftModule(moduleName, metas); - - TypeScript::SwiftDefinitionWriter swiftWriter(swiftModule, docSetPath); - llvm::SmallString<128> path; - llvm::sys::path::append(path, cla_outputDtsFolder, "swift!" + moduleName + ".d.ts"); - std::error_code error; - llvm::raw_fd_ostream file(path.str(), error, llvm::sys::fs::OF_Text); - if (error) { - std::cout << error.message(); - } else { - file << swiftWriter.write(); - file.close(); - } - - // cleanup allocated metas (bootstrap only; later we will manage via factories) - for (auto *m : metas) delete m; + bool swiftFailed = false; + if (!cla_swiftSymbolGraphDir.empty()) { + Swift::ModuleSet swiftModules = + Swift::loadSymbolGraphDirectory(cla_swiftSymbolGraphDir); + for (const auto& diagnostic : swiftModules.diagnostics) { + std::cerr << (diagnostic.severity == Swift::Severity::Error + ? "error" + : "warning") + << ": swift [" << diagnostic.code << "] " + << diagnostic.file; + if (!diagnostic.symbolId.empty()) { + std::cerr << " (" << diagnostic.symbolId << ")"; + } + std::cerr << ": " << diagnostic.message << std::endl; + } + swiftFailed = swiftModules.hasErrors(); + + auto writeFile = [](llvm::StringRef folder, llvm::StringRef fileName, + const std::string& content) { + llvm::sys::fs::create_directories(folder); + llvm::SmallString<128> path; + llvm::sys::path::append(path, folder, fileName); + std::error_code error; + llvm::raw_fd_ostream file(path.str(), error, + llvm::sys::fs::OF_Text); + if (error) { + std::cerr << "error: " << path.str().str() << ": " + << error.message() << std::endl; + return false; + } + file << content; + return true; + }; + + for (const auto& entry : swiftModules.modules) { + const Swift::Module& module = entry.second; + if (!cla_outputDtsFolder.empty()) { + TypeScript::SwiftDefinitionWriter swiftWriter(module); + swiftFailed |= !writeFile(cla_outputDtsFolder, + "swift!" + module.name + ".d.ts", + swiftWriter.write()); + } + if (!cla_swiftIROutputDir.empty()) { + swiftFailed |= !writeFile(cla_swiftIROutputDir, + module.name + ".swift-ir.json", + Swift::dumpModuleJSON(module)); } + } } std::clock_t end = clock(); double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; std::cout << "Done! Running time: " << elapsed_secs << " sec " << std::endl; - return 0; + return swiftFailed ? 1 : 0; } catch (const std::exception& e) { std::cerr << "error: " << e.what() << std::endl; return 1; diff --git a/metadata-generator/tests/CMakeLists.txt b/metadata-generator/tests/CMakeLists.txt new file mode 100644 index 000000000..cb8cbaf87 --- /dev/null +++ b/metadata-generator/tests/CMakeLists.txt @@ -0,0 +1,17 @@ +add_executable(swift-symbolgraph-tests + swift/SymbolGraphLoaderTests.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/SwiftIR.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/SymbolGraphLoader.cpp + ${CMAKE_SOURCE_DIR}/src/TypeScript/SwiftDefinitionWriter.cpp +) +target_include_directories(swift-symbolgraph-tests PRIVATE ${CMAKE_SOURCE_DIR}/src) +target_compile_definitions(swift-symbolgraph-tests PRIVATE + SWIFT_FIXTURE_GRAPHS_DIR="${CMAKE_SOURCE_DIR}/TestFixtures/SwiftDemo/symbolgraphs" + SWIFT_SNAPSHOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}/swift/snapshots" +) +target_link_libraries(swift-symbolgraph-tests ${LLVM_LINKER_FLAGS}) +set_target_properties(swift-symbolgraph-tests PROPERTIES + COMPILE_FLAGS "-Werror -Wall -Wextra -Wno-unused-parameter" +) + +add_test(NAME swift-symbolgraph-tests COMMAND swift-symbolgraph-tests) diff --git a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp new file mode 100644 index 000000000..d8e0e042e --- /dev/null +++ b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp @@ -0,0 +1,628 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "Swift/SymbolGraphLoader.h" +#include "TestHarness.h" +#include "TypeScript/SwiftDefinitionWriter.h" + +using namespace Swift; + +namespace { + +const ModuleSet& fixture() { + static ModuleSet set = loadSymbolGraphDirectory(SWIFT_FIXTURE_GRAPHS_DIR); + return set; +} + +const Module& demo() { + static const Module empty; + auto it = fixture().modules.find("SwiftDemo"); + return it == fixture().modules.end() ? empty : it->second; +} + +std::vector symbolsAt(const Module& module, + const std::string& path) { + std::vector result; + for (const auto& entry : module.symbols) { + if (llvm::join(entry.second.pathComponents, ".") == path) { + result.push_back(&entry.second); + } + } + return result; +} + +const Symbol* symbolAt(const Module& module, const std::string& path) { + auto symbols = symbolsAt(module, path); + return symbols.size() == 1 ? symbols.front() : nullptr; +} + +std::vector memberNames(const Module& module, + const Symbol& symbol) { + std::vector names; + for (const auto& id : symbol.memberIds) { + if (const Symbol* member = module.find(id)) { + names.push_back(member->name); + } + } + return names; +} + +bool contains(const std::vector& values, + const std::string& value) { + return std::find(values.begin(), values.end(), value) != values.end(); +} + +std::string diagnosticCodes(const std::vector& diagnostics) { + std::vector codes; + for (const auto& diagnostic : diagnostics) { + codes.push_back(diagnostic.code + "(" + diagnostic.message + ")"); + } + return llvm::join(codes, ", "); +} + +ModuleSet loadBuffers( + const std::vector>& buffers) { + SymbolGraphLoader loader; + for (const auto& buffer : buffers) { + loader.addBuffer(buffer.second, buffer.first); + } + return loader.finish(); +} + +std::string graphJSON(const std::string& symbols, + const std::string& relationships, + const std::string& format = "0.6.0") { + auto parts = llvm::StringRef(format).split('.'); + auto minorPatch = parts.second.split('.'); + return R"({"metadata":{"formatVersion":{"major":)" + parts.first.str() + + R"(,"minor":)" + minorPatch.first.str() + R"(,"patch":)" + + minorPatch.second.str() + + R"(},"generator":"test"},"module":{"name":"Mini","platform":{}},"symbols":[)" + + symbols + R"(],"relationships":[)" + relationships + "]}"; +} + +std::string symbolJSON(const std::string& id, const std::string& kind, + const std::string& path, + const std::string& declaration) { + return R"({"kind":{"identifier":")" + kind + + R"("},"identifier":{"precise":")" + id + R"("},"pathComponents":[")" + + path + + R"("],"names":{"title":"x"},"accessLevel":"public","declarationFragments":[)" + + declaration + "]}"; +} + +// Compares `actual` against a checked-in snapshot. NS_UPDATE_SNAPSHOTS=1 +// rewrites the snapshot instead. +void checkSnapshot(const std::string& fileName, const std::string& actual) { + llvm::SmallString<256> snapshotPath(SWIFT_SNAPSHOT_DIR); + llvm::sys::path::append(snapshotPath, fileName); + + if (const char* update = std::getenv("NS_UPDATE_SNAPSHOTS"); + update && *update == '1') { + std::error_code error; + llvm::raw_fd_ostream out(snapshotPath, error, llvm::sys::fs::OF_Text); + REQUIRE(!error); + out << actual; + return; + } + + auto expected = llvm::MemoryBuffer::getFile(snapshotPath, /*IsText*/ true); + if (!expected) { + TestHarness::fail(__FILE__, __LINE__, + "missing snapshot " + snapshotPath.str().str() + + " (run with NS_UPDATE_SNAPSHOTS=1)"); + return; + } + if ((*expected)->getBuffer() != actual) { + llvm::SmallString<256> actualPath(snapshotPath); + actualPath += ".actual"; + std::error_code error; + llvm::raw_fd_ostream out(actualPath, error, llvm::sys::fs::OF_Text); + out << actual; + TestHarness::fail(__FILE__, __LINE__, + "snapshot mismatch: diff " + snapshotPath.str().str() + + " " + actualPath.str().str()); + } +} + +} // namespace + +TEST(LoadsFixtureWithoutDiagnostics) { + CHECK_EQ(fixture().modules.size(), size_t(1)); + CHECK_EQ(diagnosticCodes(fixture().diagnostics), std::string()); + const Module& module = demo(); + CHECK_EQ(module.name, std::string("SwiftDemo")); + CHECK_EQ(module.graphFiles.size(), size_t(2)); + CHECK_EQ(module.platform.operatingSystem, std::string("ios")); + CHECK_EQ(module.platform.environment, std::string("simulator")); +} + +TEST(TopLevelDeclarationsInSourceOrder) { + std::vector names; + for (const auto& id : demo().topLevelIds) { + names.push_back(demo().find(id)->name); + } + std::vector expected = {"Greeter", "Demo", + "Point", "Flavor", + "Shape", "Polygon", + "Square", "ShapeError", + "Measurement", "Ring", + "Counter", "Canvas", + "Loader", "makeDefaultPoint()", + "defaultFlavor", "globalCounter", + "Coordinates"}; + CHECK_EQ(llvm::join(names, ","), llvm::join(expected, ",")); +} + +TEST(NominalKinds) { + CHECK(symbolAt(demo(), "Demo")->kind == SymbolKind::Class); + CHECK(symbolAt(demo(), "Point")->kind == SymbolKind::Struct); + CHECK(symbolAt(demo(), "Flavor")->kind == SymbolKind::Enum); + CHECK(symbolAt(demo(), "Greeter")->kind == SymbolKind::Protocol); + CHECK(symbolAt(demo(), "Counter")->kind == SymbolKind::Actor); + CHECK(symbolAt(demo(), "Polygon")->access == AccessLevel::Open); + CHECK(symbolAt(demo(), "Demo")->access == AccessLevel::Public); +} + +TEST(ExtensionMembersJoinTheirType) { + const Symbol* demoType = symbolAt(demo(), "Demo"); + REQUIRE(demoType); + auto names = memberNames(demo(), *demoType); + CHECK(contains(names, "init()")); + CHECK(contains(names, "greet(name:)")); + CHECK(contains(names, "greet(name:times:)")); + CHECK(contains(names, "version")); + + const Symbol* version = symbolAt(demo(), "Demo.version"); + REQUIRE(version); + CHECK(version->isStatic); + CHECK_EQ(version->parentId, demoType->preciseId); +} + +TEST(OverloadsKeepDistinctIdentities) { + auto overloads = symbolsAt(demo(), "Polygon.scale(by:)"); + REQUIRE(overloads.size() == 2); + CHECK(overloads[0]->preciseId != overloads[1]->preciseId); + std::vector types; + for (const Symbol* overload : overloads) { + REQUIRE(overload->parameters.size() == 1); + CHECK_EQ(overload->parameters[0].label, std::string("by")); + CHECK_EQ(overload->parameters[0].internalName, std::string("factor")); + types.push_back(overload->parameters[0].type.spelling); + } + std::sort(types.begin(), types.end()); + CHECK_EQ(llvm::join(types, ","), std::string("Double,Int")); +} + +TEST(ParameterLabels) { + const Symbol* describe = symbolAt(demo(), "Polygon.describe(_:)"); + REQUIRE(describe && describe->parameters.size() == 1); + CHECK_EQ(describe->parameters[0].label, std::string()); + CHECK_EQ(describe->parameters[0].internalName, std::string("polygon")); + CHECK_EQ(describe->parameters[0].type.spelling, std::string("Polygon?")); + CHECK(describe->isStatic); + + const Symbol* fetch = symbolAt(demo(), "Loader.fetch(url:)"); + REQUIRE(fetch && fetch->parameters.size() == 1); + CHECK_EQ(fetch->parameters[0].label, std::string("url")); + CHECK_EQ(fetch->parameters[0].internalName, std::string("url")); + REQUIRE(fetch->parameters[0].type.fragments.size() == 1); + CHECK_EQ(fetch->parameters[0].type.fragments[0].preciseIdentifier, + std::string("s:10Foundation3URLV")); + + const Symbol* plus = symbolAt(demo(), "Ring.+(_:_:)"); + REQUIRE(plus && plus->parameters.size() == 2); + CHECK(plus->kind == SymbolKind::Operator); + CHECK(plus->isStatic); + CHECK_EQ(plus->parameters[1].internalName, std::string("rhs")); + CHECK_EQ(plus->returnType->spelling, std::string("Ring")); +} + +TEST(Effects) { + const Symbol* fetch = symbolAt(demo(), "Loader.fetch(url:)"); + REQUIRE(fetch); + CHECK(fetch->isAsync); + CHECK(fetch->isThrowing); + CHECK_EQ(fetch->returnType->spelling, std::string("String")); + + const Symbol* load = symbolAt(demo(), "Loader.load(path:)"); + REQUIRE(load); + CHECK(!load->isAsync); + CHECK(load->isThrowing); + + const Symbol* wait = symbolAt(demo(), "Loader.wait(seconds:)"); + REQUIRE(wait); + CHECK(wait->isAsync); + CHECK(!wait->isThrowing); + CHECK(!wait->returnType); +} + +TEST(EffectsInsideClosureTypesDoNotLeak) { + // The synthesized actor method takes an `async throws(E)` closure; only the + // method's own effects may be recorded. + for (const Symbol* symbol : + symbolsAt(demo(), "Counter.withSerialExecutor(_:)")) { + REQUIRE(symbol->parameters.size() == 1); + CHECK(symbol->isThrowing); + CHECK_EQ(symbol->thrownType.spelling, std::string("E")); + CHECK_EQ(symbol->returnType->spelling, std::string("T")); + CHECK(symbol->isSynthesized); + } +} + +TEST(Properties) { + const Symbol* x = symbolAt(demo(), "Point.x"); + REQUIRE(x && x->valueType); + CHECK_EQ(x->valueType->spelling, std::string("Double")); + CHECK(x->isSettable); + + const Symbol* vertexCount = symbolAt(demo(), "Polygon.vertexCount"); + REQUIRE(vertexCount); + CHECK(!vertexCount->isSettable); + + const Symbol* name = symbolAt(demo(), "Polygon.name"); + REQUIRE(name); + CHECK(name->isLet); + CHECK(!name->isSettable); + + const Symbol* shared = symbolAt(demo(), "Polygon.shared"); + REQUIRE(shared && shared->valueType); + CHECK(shared->isStatic); + CHECK_EQ(shared->valueType->spelling, std::string("Polygon")); + + const Symbol* area = symbolAt(demo(), "Shape.area"); + REQUIRE(area); + CHECK(area->isProtocolRequirement); + CHECK(!area->isSettable); + + const Symbol* globalCounter = symbolAt(demo(), "globalCounter"); + REQUIRE(globalCounter); + CHECK(globalCounter->kind == SymbolKind::Variable); + CHECK(globalCounter->isSettable); +} + +TEST(Subscripts) { + const Symbol* subscript = symbolAt(demo(), "Polygon.subscript(_:)"); + REQUIRE(subscript && subscript->valueType); + CHECK(subscript->kind == SymbolKind::InstanceSubscript); + CHECK_EQ(subscript->valueType->spelling, std::string("Point")); + CHECK(!subscript->isSettable); + REQUIRE(subscript->parameters.size() == 1); + CHECK_EQ(subscript->parameters[0].label, std::string()); + CHECK_EQ(subscript->parameters[0].internalName, std::string("index")); +} + +TEST(Initializers) { + const Symbol* failable = symbolAt(demo(), "Polygon.init(name:)"); + REQUIRE(failable); + CHECK(failable->isFailable); + CHECK(contains(failable->modifiers, "convenience")); + + const Symbol* designated = + symbolAt(demo(), "Polygon.init(name:vertexCount:)"); + REQUIRE(designated); + CHECK(!designated->isFailable); + CHECK_EQ(designated->parameters.size(), size_t(2)); + + const Symbol* rawValue = symbolAt(demo(), "Flavor.init(rawValue:)"); + REQUIRE(rawValue); + CHECK(rawValue->isFailable); + CHECK_EQ(rawValue->parameters[0].type.spelling, std::string("Int")); +} + +TEST(EnumCases) { + const Symbol* area = symbolAt(demo(), "Measurement.area(width:height:)"); + REQUIRE(area && area->parameters.size() == 2); + CHECK(area->kind == SymbolKind::EnumCase); + CHECK_EQ(area->parameters[0].label, std::string("width")); + CHECK_EQ(area->parameters[1].type.spelling, std::string("Double")); + + const Symbol* length = symbolAt(demo(), "Measurement.length(_:)"); + REQUIRE(length && length->parameters.size() == 1); + CHECK_EQ(length->parameters[0].label, std::string()); + + const Symbol* none = symbolAt(demo(), "Measurement.none"); + REQUIRE(none); + CHECK(none->parameters.empty()); + + const Symbol* flavor = symbolAt(demo(), "Flavor"); + REQUIRE(flavor); + auto names = memberNames(demo(), *flavor); + CHECK(contains(names, "vanilla")); + CHECK(contains(names, "chocolate")); +} + +TEST(NestedTypes) { + const Symbol* unit = symbolAt(demo(), "Measurement.Unit"); + const Symbol* measurement = symbolAt(demo(), "Measurement"); + REQUIRE(unit && measurement); + CHECK(unit->kind == SymbolKind::Struct); + CHECK_EQ(unit->parentId, measurement->preciseId); + CHECK(!contains(demo().topLevelIds, unit->preciseId)); +} + +TEST(ParameterModifiersAndAttributes) { + const Symbol* update = symbolAt(demo(), "Loader.update(_:)"); + REQUIRE(update && update->parameters.size() == 1); + CHECK_EQ(update->parameters[0].modifier, std::string("inout")); + CHECK_EQ(update->parameters[0].type.spelling, std::string("Point")); + + const Symbol* completion = symbolAt(demo(), "Loader.withCompletion(_:)"); + REQUIRE(completion && completion->parameters.size() == 1); + CHECK(contains(completion->parameters[0].attributes, "@escaping")); + CHECK_EQ(completion->parameters[0].type.spelling, + std::string("(Result) -> Void")); + + const Symbol* each = symbolAt(demo(), "Loader.each(_:)"); + REQUIRE(each && each->parameters.size() == 1); + CHECK(each->parameters[0].attributes.empty()); + + for (const Symbol* symbol : + symbolsAt(demo(), "Counter.preconditionIsolated(_:file:line:)")) { + REQUIRE(symbol->parameters.size() == 3); + CHECK(contains(symbol->parameters[0].attributes, "@autoclosure")); + CHECK_EQ(symbol->parameters[0].defaultValue, std::string("String()")); + CHECK_EQ(symbol->parameters[1].defaultValue, std::string("#fileID")); + } +} + +TEST(Generics) { + const Symbol* transform = symbolAt(demo(), "Loader.transform(_:)"); + REQUIRE(transform); + REQUIRE(transform->genericParameters.size() == 1); + CHECK_EQ(transform->genericParameters[0].name, std::string("T")); + REQUIRE(transform->genericConstraints.size() == 1); + CHECK_EQ(transform->genericConstraints[0].kind, std::string("conformance")); + CHECK_EQ(transform->genericConstraints[0].rhs, std::string("Shape")); + CHECK_EQ(transform->returnType->spelling, std::string("T")); +} + +TEST(ActorIsolation) { + const Symbol* canvas = symbolAt(demo(), "Canvas"); + REQUIRE(canvas); + CHECK(contains(canvas->attributes, "@MainActor")); + CHECK(contains(canvas->modifiers, "final")); + + const Symbol* label = symbolAt(demo(), "Counter.label()"); + REQUIRE(label); + CHECK(contains(label->attributes, "nonisolated")); + + const Symbol* increment = symbolAt(demo(), "Counter.increment()"); + REQUIRE(increment); + CHECK(increment->attributes.empty()); +} + +TEST(InheritanceConformanceAndOverrides) { + const Symbol* square = symbolAt(demo(), "Square"); + const Symbol* polygon = symbolAt(demo(), "Polygon"); + const Symbol* shape = symbolAt(demo(), "Shape"); + const Symbol* greeter = symbolAt(demo(), "Greeter"); + REQUIRE(square && polygon && shape && greeter); + CHECK_EQ(square->superclassId, polygon->preciseId); + CHECK(contains(square->conformances, shape->preciseId)); + CHECK(contains(shape->conformances, greeter->preciseId)); + + const Symbol* override = nullptr; + for (const Symbol* candidate : symbolsAt(demo(), "Square.scale(by:)")) { + override = candidate; + } + REQUIRE(override); + CHECK(contains(override->modifiers, "override")); + REQUIRE(!override->overriddenId.empty()); + const Symbol* base = demo().find(override->overriddenId); + REQUIRE(base); + CHECK_EQ(base->parameters[0].type.spelling, std::string("Double")); + + const Symbol* point = symbolAt(demo(), "Point"); + REQUIRE(point); + CHECK(contains(point->conformances, "s:s23CustomStringConvertibleP")); + CHECK_EQ(demo().externalNames.at("s:s23CustomStringConvertibleP"), + std::string("Swift.CustomStringConvertible")); +} + +TEST(ProtocolRequirementsAndWitnesses) { + const Symbol* greeter = symbolAt(demo(), "Greeter"); + REQUIRE(greeter); + auto names = memberNames(demo(), *greeter); + CHECK_EQ(llvm::join(names, ","), std::string("greet(name:)")); + + const Symbol* requirement = symbolAt(demo(), "Greeter.greet(name:)"); + const Symbol* witness = symbolAt(demo(), "Demo.greet(name:)"); + REQUIRE(requirement && witness); + CHECK(requirement->isProtocolRequirement); + CHECK(!witness->isProtocolRequirement); + CHECK_EQ(witness->sourceOriginId, requirement->preciseId); +} + +TEST(ExtensionsOfExternalTypes) { + auto it = demo().externalTypes.find("s:SS"); + REQUIRE(it != demo().externalTypes.end()); + const ExternalType& string = it->second; + CHECK_EQ(string.qualifiedName, std::string("Swift.String")); + CHECK_EQ(string.extendedModule, std::string("Swift")); + CHECK_EQ(string.typeKind, std::string("swift.struct")); + REQUIRE(string.memberIds.size() == 1); + const Symbol* shouted = demo().find(string.memberIds[0]); + REQUIRE(shouted); + CHECK_EQ(shouted->name, std::string("shouted")); + CHECK_EQ(shouted->sourceGraph, std::string("SwiftDemo@Swift.symbols.json")); + CHECK(!contains(demo().topLevelIds, shouted->preciseId)); + + auto array = demo().externalTypes.find("s:Sa"); + REQUIRE(array != demo().externalTypes.end()); + REQUIRE(array->second.memberIds.size() == 1); + const Symbol* centroid = demo().find(array->second.memberIds[0]); + REQUIRE(centroid && centroid->extension); + REQUIRE(centroid->extension->constraints.size() == 1); + CHECK_EQ(centroid->extension->constraints[0].kind, std::string("sameType")); + CHECK_EQ(centroid->extension->constraints[0].rhs, std::string("Point")); +} + +TEST(Availability) { + const Symbol* modern = symbolAt(demo(), "Loader.modernOnly()"); + REQUIRE(modern && modern->availability.size() == 1); + CHECK_EQ(modern->availability[0].domain, std::string("iOS")); + REQUIRE(modern->availability[0].introduced); + CHECK_EQ(modern->availability[0].introduced->major, 16); + + const Symbol* legacy = symbolAt(demo(), "Loader.legacyFetch()"); + REQUIRE(legacy && legacy->availability.size() == 1); + CHECK_EQ(legacy->availability[0].domain, std::string("*")); + CHECK(legacy->availability[0].isUnconditionallyDeprecated); + CHECK_EQ(legacy->availability[0].message, + std::string("Use fetch(url:) instead")); + + const Symbol* old = symbolAt(demo(), "Loader.oldFetch()"); + REQUIRE(old && old->availability.size() == 1); + REQUIRE(old->availability[0].deprecated); + CHECK_EQ(old->availability[0].deprecated->major, 17); + CHECK_EQ(old->availability[0].renamed, std::string("fetch(url:)")); +} + +TEST(SynthesizedMembers) { + const Symbol* hashValue = symbolAt(demo(), "Flavor.hashValue"); + REQUIRE(hashValue); + CHECK(hashValue->isSynthesized); + CHECK(!hashValue->location); + CHECK(!hashValue->sourceOriginId.empty()); + + const Symbol* greet = symbolAt(demo(), "Demo.greet(name:)"); + REQUIRE(greet); + CHECK(!greet->isSynthesized); +} + +TEST(NonPublicDeclarationsAreAbsent) { + CHECK(symbolsAt(demo(), "Polygon.hiddenHelper()").empty()); +} + +TEST(TypeAliases) { + const Symbol* alias = symbolAt(demo(), "Coordinates"); + REQUIRE(alias && alias->aliasedType); + CHECK_EQ(alias->aliasedType->spelling, + std::string("(latitude: Double, longitude: Double)")); +} + +TEST(IRSnapshot) { checkSnapshot("SwiftDemo.ir.json", dumpModuleJSON(demo())); } + +TEST(TypeScriptSnapshot) { + TypeScript::SwiftDefinitionWriter writer(demo()); + checkSnapshot("swift!SwiftDemo.d.ts", writer.write()); +} + +TEST(LoadOrderDoesNotChangeTheIR) { + std::vector diagnostics; + auto files = + SymbolGraphLoader::findGraphFiles(SWIFT_FIXTURE_GRAPHS_DIR, diagnostics); + REQUIRE(files.size() == 2); + + SymbolGraphLoader reversed; + for (auto it = files.rbegin(); it != files.rend(); ++it) { + reversed.addFile(*it, llvm::sys::path::filename(*it).str()); + } + ModuleSet set = reversed.finish(); + REQUIRE(set.modules.count("SwiftDemo")); + CHECK(dumpModuleJSON(set.modules.at("SwiftDemo")) == dumpModuleJSON(demo())); +} + +TEST(InvalidJSONIsAnError) { + ModuleSet set = loadBuffers({{"broken.symbols.json", "{\"metadata\": "}}); + CHECK(set.hasErrors()); + CHECK(set.modules.empty()); + REQUIRE(set.diagnostics.size() == 1); + CHECK_EQ(set.diagnostics[0].code, std::string("invalid-json")); + CHECK_EQ(set.diagnostics[0].file, std::string("broken.symbols.json")); +} + +TEST(UnsupportedFormatMajorIsRejected) { + ModuleSet set = + loadBuffers({{"future.symbols.json", graphJSON("", "", "1.0.0")}}); + CHECK(set.hasErrors()); + CHECK(set.modules.empty()); + CHECK_EQ(set.diagnostics[0].code, std::string("unsupported-format-version")); +} + +TEST(NewerFormatMinorLoadsWithWarning) { + ModuleSet set = + loadBuffers({{"newer.symbols.json", graphJSON("", "", "0.9.0")}}); + CHECK(!set.hasErrors()); + CHECK_EQ(set.modules.count("Mini"), size_t(1)); + REQUIRE(set.diagnostics.size() == 1); + CHECK_EQ(set.diagnostics[0].code, std::string("newer-format-version")); +} + +TEST(UnknownKindsAreReportedAndKept) { + std::string symbol = + symbolJSON("s:4Mini1xv", "swift.newfangled", "x", + R"({"kind":"keyword","spelling":"newfangled"})"); + ModuleSet set = loadBuffers({{"mini.symbols.json", graphJSON(symbol, "")}}); + REQUIRE(set.modules.count("Mini")); + const Symbol* x = set.modules.at("Mini").find("s:4Mini1xv"); + REQUIRE(x); + CHECK(x->kind == SymbolKind::Unknown); + CHECK_EQ(x->kindIdentifier, std::string("swift.newfangled")); + bool reported = false; + for (const auto& diagnostic : set.diagnostics) { + reported |= diagnostic.code == "unknown-symbol-kind" && + diagnostic.symbolId == "s:4Mini1xv"; + } + CHECK(reported); +} + +TEST(DanglingRelationshipsAreReported) { + ModuleSet set = loadBuffers( + {{"mini.symbols.json", + graphJSON( + "", + R"({"kind":"memberOf","source":"s:missing","target":"s:alsoMissing"})")}}); + REQUIRE(set.diagnostics.size() == 1); + CHECK_EQ(set.diagnostics[0].code, std::string("dangling-relationship")); + CHECK(!set.hasErrors()); +} + +TEST(ConflictingDuplicateSymbolsAreReported) { + std::string first = symbolJSON( + "s:4Mini1fyyF", "swift.func", "f()", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"f"},{"kind":"text","spelling":"()"})json"); + std::string second = symbolJSON( + "s:4Mini1fyyF", "swift.func", "f()", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"f"},{"kind":"text","spelling":"() async"})json"); + ModuleSet set = loadBuffers({{"a.symbols.json", graphJSON(first, "")}, + {"b.symbols.json", graphJSON(second, "")}}); + REQUIRE(set.modules.count("Mini")); + CHECK_EQ(set.modules.at("Mini").symbols.size(), size_t(1)); + CHECK_EQ(set.modules.at("Mini").find("s:4Mini1fyyF")->sourceGraph, + std::string("a.symbols.json")); + REQUIRE(set.diagnostics.size() == 1); + CHECK_EQ(set.diagnostics[0].code, std::string("duplicate-symbol")); + + ModuleSet identical = loadBuffers({{"a.symbols.json", graphJSON(first, "")}, + {"b.symbols.json", graphJSON(first, "")}}); + CHECK(identical.diagnostics.empty()); +} + +TEST(LabelMismatchesAreReported) { + // Name claims a labeled argument the declaration does not have. + std::string symbol = symbolJSON( + "s:4Mini1fyySiF", "swift.func", "f(value:)", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"f"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int"},{"kind":"text","spelling":")"})json"); + ModuleSet set = loadBuffers({{"mini.symbols.json", graphJSON(symbol, "")}}); + REQUIRE(set.diagnostics.size() == 1); + CHECK_EQ(set.diagnostics[0].code, std::string("parameter-label-mismatch")); +} + +TEST(MissingDirectoryIsAnError) { + ModuleSet set = + loadSymbolGraphDirectory(SWIFT_FIXTURE_GRAPHS_DIR "/does-not-exist"); + CHECK(set.hasErrors()); + CHECK_EQ(set.diagnostics[0].code, std::string("missing-directory")); +} + +int main(int argc, char** argv) { + return TestHarness::runAll(argc > 1 ? argv[1] : ""); +} diff --git a/metadata-generator/tests/swift/TestHarness.h b/metadata-generator/tests/swift/TestHarness.h new file mode 100644 index 000000000..60c93b5ab --- /dev/null +++ b/metadata-generator/tests/swift/TestHarness.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace TestHarness { + +struct TestCase { + const char* name; + std::function body; +}; + +inline std::vector& registry() { + static std::vector tests; + return tests; +} + +inline int& failureCount() { + static int failures = 0; + return failures; +} + +struct Registrar { + Registrar(const char* name, std::function body) { + registry().push_back(TestCase{name, std::move(body)}); + } +}; + +inline void fail(const char* file, int line, const std::string& message) { + failureCount()++; + std::cerr << file << ":" << line << ": FAILED: " << message << std::endl; +} + +// Runs every registered test whose name contains `filter`. +inline int runAll(const std::string& filter) { + int ran = 0; + for (const auto& test : registry()) { + if (!filter.empty() && + std::string(test.name).find(filter) == std::string::npos) { + continue; + } + int before = failureCount(); + test.body(); + ran++; + std::cout << (failureCount() == before ? "[ OK ] " : "[FAIL] ") << test.name + << std::endl; + } + std::cout << ran << " tests, " << failureCount() << " failed checks" + << std::endl; + return failureCount() == 0 && ran > 0 ? 0 : 1; +} + +} // namespace TestHarness + +#define TEST_CONCAT_INNER(a, b) a##b +#define TEST_CONCAT(a, b) TEST_CONCAT_INNER(a, b) + +#define TEST(name) \ + static void TEST_CONCAT(test_, name)(); \ + static TestHarness::Registrar TEST_CONCAT(registrar_, name)( \ + #name, TEST_CONCAT(test_, name)); \ + static void TEST_CONCAT(test_, name)() + +#define CHECK(condition) \ + do { \ + if (!(condition)) { \ + TestHarness::fail(__FILE__, __LINE__, "CHECK(" #condition ")"); \ + } \ + } while (0) + +#define CHECK_EQ(actual, expected) \ + do { \ + const auto& actualValue = (actual); \ + const auto& expectedValue = (expected); \ + if (!(actualValue == expectedValue)) { \ + std::ostringstream message; \ + message << #actual << " == " << #expected \ + << "\n actual: " << actualValue \ + << "\n expected: " << expectedValue; \ + TestHarness::fail(__FILE__, __LINE__, message.str()); \ + } \ + } while (0) + +// Stops the current test when a precondition for later checks fails. +#define REQUIRE(condition) \ + do { \ + if (!(condition)) { \ + TestHarness::fail(__FILE__, __LINE__, "REQUIRE(" #condition ")"); \ + return; \ + } \ + } while (0) diff --git a/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json b/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json new file mode 100644 index 000000000..4fe3324cf --- /dev/null +++ b/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json @@ -0,0 +1,2622 @@ +{ + "module": "SwiftDemo", + "formatVersion": "0.6.0", + "platform": { + "architecture": "arm64", + "vendor": "apple", + "operatingSystem": "ios", + "environment": "simulator", + "minimumVersion": "15.0.0" + }, + "graphFiles": [ + "SwiftDemo.symbols.json", + "SwiftDemo@Swift.symbols.json" + ], + "topLevel": [ + "s:9SwiftDemo7GreeterP", + "s:9SwiftDemo0B0C", + "s:9SwiftDemo5PointV", + "s:9SwiftDemo6FlavorO", + "s:9SwiftDemo5ShapeP", + "s:9SwiftDemo7PolygonC", + "s:9SwiftDemo6SquareC", + "s:9SwiftDemo10ShapeErrorO", + "s:9SwiftDemo11MeasurementO", + "s:9SwiftDemo4RingV", + "s:9SwiftDemo7CounterC", + "s:9SwiftDemo6CanvasC", + "s:9SwiftDemo6LoaderC", + "s:9SwiftDemo16makeDefaultPointAA0E0VyF", + "s:9SwiftDemo13defaultFlavorAA0D0Ovp", + "s:9SwiftDemo13globalCounterSivp", + "s:9SwiftDemo11Coordinatesa" + ], + "externalTypes": [ + { + "id": "s:SS", + "qualifiedName": "Swift.String", + "extendedModule": "Swift", + "typeKind": "swift.struct", + "members": [ + "s:SS9SwiftDemoE7shoutedSSvp" + ] + }, + { + "id": "s:Sa", + "qualifiedName": "Swift.Array", + "extendedModule": "Swift", + "typeKind": "swift.struct", + "members": [ + "s:Sa9SwiftDemoAA5PointVRszlE8centroidACyF" + ] + } + ], + "externalNames": { + "s:SH": "Swift.Hashable", + "s:SQ": "Swift.Equatable", + "s:SS": "Swift.String", + "s:SY": "Swift.RawRepresentable", + "s:Sa": "Swift.Array", + "s:ScA": "_Concurrency.Actor", + "s:s16SendableMetatypeP": "Swift.SendableMetatype", + "s:s23CustomStringConvertibleP": "Swift.CustomStringConvertible", + "s:s5ErrorP": "Swift.Error", + "s:s8CopyableP": "Swift.Copyable", + "s:s8SendableP": "Swift.Sendable", + "s:s9EscapableP": "Swift.Escapable" + }, + "symbols": [ + { + "id": "s:9SwiftDemo0B0C", + "kind": "class", + "path": "Demo", + "name": "Demo", + "access": "public", + "declaration": "class Demo", + "location": "file://Sources/SwiftDemo/Demo.swift:4:13", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo0B0CACycfc", + "s:9SwiftDemo0B0C5greet4nameS2S_tF", + "s:9SwiftDemo0B0C5greet4name5timesS2S_SitF", + "s:9SwiftDemo0B0C7versionSSvpZ" + ], + "conformances": [ + "s:9SwiftDemo7GreeterP" + ] + }, + { + "id": "s:9SwiftDemo0B0C5greet4name5timesS2S_SitF", + "kind": "instanceMethod", + "path": "Demo.greet(name:times:)", + "name": "greet(name:times:)", + "access": "public", + "declaration": "func greet(name: String, times: Int) -> String", + "parameters": [ + { + "label": "name", + "internalName": "name", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + }, + { + "label": "times", + "internalName": "times", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "extension": { + "extendedModule": "SwiftDemo", + "typeKind": "swift.class" + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:1:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo0B0C" + }, + { + "id": "s:9SwiftDemo0B0C5greet4nameS2S_tF", + "kind": "instanceMethod", + "path": "Demo.greet(name:)", + "name": "greet(name:)", + "access": "public", + "declaration": "func greet(name: String) -> String", + "parameters": [ + { + "label": "name", + "internalName": "name", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "location": "file://Sources/SwiftDemo/Demo.swift:6:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo0B0C", + "sourceOrigin": "s:9SwiftDemo7GreeterP5greet4nameS2S_tF" + }, + { + "id": "s:9SwiftDemo0B0C7versionSSvpZ", + "kind": "typeProperty", + "path": "Demo.version", + "name": "version", + "access": "public", + "declaration": "static var version: String { get }", + "modifiers": [ + "static" + ], + "static": true, + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": false, + "extension": { + "extendedModule": "SwiftDemo", + "typeKind": "swift.class" + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:5:22", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo0B0C" + }, + { + "id": "s:9SwiftDemo0B0CACycfc", + "kind": "initializer", + "path": "Demo.init()", + "name": "init()", + "access": "public", + "declaration": "init()", + "location": "file://Sources/SwiftDemo/Demo.swift:5:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo0B0C" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO", + "kind": "enum", + "path": "ShapeError", + "name": "ShapeError", + "access": "public", + "declaration": "enum ShapeError", + "location": "file://Sources/SwiftDemo/Shapes.swift:49:12", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF", + "s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF", + "s:9SwiftDemo10ShapeErrorO7unknownyA2CmF", + "s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO" + ], + "conformances": [ + "s:s16SendableMetatypeP", + "s:s5ErrorP", + "s:s8SendableP" + ] + }, + { + "id": "s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF", + "kind": "enumCase", + "path": "ShapeError.invalidSide(_:)", + "name": "invalidSide(_:)", + "access": "public", + "declaration": "case invalidSide(Double)", + "parameters": [ + { + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:50:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo10ShapeErrorO" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF", + "kind": "enumCase", + "path": "ShapeError.tooManySides(count:limit:)", + "name": "tooManySides(count:limit:)", + "access": "public", + "declaration": "case tooManySides(count: Int, limit: Int)", + "parameters": [ + { + "label": "count", + "internalName": "count", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + }, + { + "label": "limit", + "internalName": "limit", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:51:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo10ShapeErrorO" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO7unknownyA2CmF", + "kind": "enumCase", + "path": "ShapeError.unknown", + "name": "unknown", + "access": "public", + "declaration": "case unknown", + "location": "file://Sources/SwiftDemo/Shapes.swift:52:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo10ShapeErrorO" + }, + { + "id": "s:9SwiftDemo11Coordinatesa", + "kind": "typeAlias", + "path": "Coordinates", + "name": "Coordinates", + "access": "public", + "declaration": "typealias Coordinates = (latitude: Double, longitude: Double)", + "aliasedType": { + "spelling": "(latitude: Double, longitude: Double)", + "references": [ + "s:Sd", + "s:Sd" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:136:17", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:9SwiftDemo11MeasurementO", + "kind": "enum", + "path": "Measurement", + "name": "Measurement", + "access": "public", + "declaration": "enum Measurement", + "location": "file://Sources/SwiftDemo/Shapes.swift:55:12", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo11MeasurementO6lengthyACSdcACmF", + "s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF", + "s:9SwiftDemo11MeasurementO4noneyA2CmF", + "s:9SwiftDemo11MeasurementO4UnitV", + "s:9SwiftDemo11MeasurementO6isNoneSbvp" + ] + }, + { + "id": "s:9SwiftDemo11MeasurementO4UnitV", + "kind": "struct", + "path": "Measurement.Unit", + "name": "Unit", + "access": "public", + "declaration": "struct Unit", + "location": "file://Sources/SwiftDemo/Shapes.swift:60:18", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO", + "members": [ + "s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp", + "s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc" + ] + }, + { + "id": "s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc", + "kind": "initializer", + "path": "Measurement.Unit.init(symbol:)", + "name": "init(symbol:)", + "access": "public", + "declaration": "init(symbol: String)", + "parameters": [ + { + "label": "symbol", + "internalName": "symbol", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:62:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO4UnitV" + }, + { + "id": "s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp", + "kind": "instanceProperty", + "path": "Measurement.Unit.symbol", + "name": "symbol", + "access": "public", + "declaration": "var symbol: String", + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:61:19", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO4UnitV" + }, + { + "id": "s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF", + "kind": "enumCase", + "path": "Measurement.area(width:height:)", + "name": "area(width:height:)", + "access": "public", + "declaration": "case area(width: Double, height: Double)", + "parameters": [ + { + "label": "width", + "internalName": "width", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + }, + { + "label": "height", + "internalName": "height", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:57:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO" + }, + { + "id": "s:9SwiftDemo11MeasurementO4noneyA2CmF", + "kind": "enumCase", + "path": "Measurement.none", + "name": "none", + "access": "public", + "declaration": "case none", + "location": "file://Sources/SwiftDemo/Shapes.swift:58:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO" + }, + { + "id": "s:9SwiftDemo11MeasurementO6isNoneSbvp", + "kind": "instanceProperty", + "path": "Measurement.isNone", + "name": "isNone", + "access": "public", + "declaration": "var isNone: Bool { get }", + "valueType": { + "spelling": "Bool", + "references": [ + "s:Sb" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:65:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO" + }, + { + "id": "s:9SwiftDemo11MeasurementO6lengthyACSdcACmF", + "kind": "enumCase", + "path": "Measurement.length(_:)", + "name": "length(_:)", + "access": "public", + "declaration": "case length(Double)", + "parameters": [ + { + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:56:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo11MeasurementO" + }, + { + "id": "s:9SwiftDemo13defaultFlavorAA0D0Ovp", + "kind": "variable", + "path": "defaultFlavor", + "name": "defaultFlavor", + "access": "public", + "declaration": "let defaultFlavor: Flavor", + "valueType": { + "spelling": "Flavor", + "references": [ + "s:9SwiftDemo6FlavorO" + ] + }, + "settable": false, + "let": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:134:11", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:9SwiftDemo13globalCounterSivp", + "kind": "variable", + "path": "globalCounter", + "name": "globalCounter", + "access": "public", + "declaration": "var globalCounter: Int", + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:135:11", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:9SwiftDemo16makeDefaultPointAA0E0VyF", + "kind": "function", + "path": "makeDefaultPoint()", + "name": "makeDefaultPoint()", + "access": "public", + "declaration": "func makeDefaultPoint() -> Point", + "returns": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:133:12", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:9SwiftDemo4RingV", + "kind": "struct", + "path": "Ring", + "name": "Ring", + "access": "public", + "declaration": "struct Ring", + "location": "file://Sources/SwiftDemo/Shapes.swift:71:14", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo4RingV5innerAA5PointVvp", + "s:9SwiftDemo4RingV5outerAA5PointVvp", + "s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc", + "s:9SwiftDemo4RingV6expand2byySd_tF", + "s:9SwiftDemo4RingV1poiyA2C_ACtFZ" + ] + }, + { + "id": "s:9SwiftDemo4RingV1poiyA2C_ACtFZ", + "kind": "operator", + "path": "Ring.+(_:_:)", + "name": "+(_:_:)", + "access": "public", + "declaration": "static func + (lhs: Ring, rhs: Ring) -> Ring", + "modifiers": [ + "static" + ], + "static": true, + "parameters": [ + { + "internalName": "lhs", + "type": { + "spelling": "Ring", + "references": [ + "s:9SwiftDemo4RingV" + ] + } + }, + { + "internalName": "rhs", + "type": { + "spelling": "Ring", + "references": [ + "s:9SwiftDemo4RingV" + ] + } + } + ], + "returns": { + "spelling": "Ring", + "references": [ + "s:9SwiftDemo4RingV" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:85:23", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo4RingV" + }, + { + "id": "s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc", + "kind": "initializer", + "path": "Ring.init(inner:outer:)", + "name": "init(inner:outer:)", + "access": "public", + "declaration": "init(inner: Point, outer: Point)", + "parameters": [ + { + "label": "inner", + "internalName": "inner", + "type": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + } + }, + { + "label": "outer", + "internalName": "outer", + "type": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:75:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo4RingV" + }, + { + "id": "s:9SwiftDemo4RingV5innerAA5PointVvp", + "kind": "instanceProperty", + "path": "Ring.inner", + "name": "inner", + "access": "public", + "declaration": "var inner: Point", + "valueType": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:72:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo4RingV" + }, + { + "id": "s:9SwiftDemo4RingV5outerAA5PointVvp", + "kind": "instanceProperty", + "path": "Ring.outer", + "name": "outer", + "access": "public", + "declaration": "var outer: Point", + "valueType": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:73:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo4RingV" + }, + { + "id": "s:9SwiftDemo4RingV6expand2byySd_tF", + "kind": "instanceMethod", + "path": "Ring.expand(by:)", + "name": "expand(by:)", + "access": "public", + "declaration": "mutating func expand(by delta: Double)", + "modifiers": [ + "mutating" + ], + "parameters": [ + { + "label": "by", + "internalName": "delta", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:80:25", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo4RingV" + }, + { + "id": "s:9SwiftDemo5PointV", + "kind": "struct", + "path": "Point", + "name": "Point", + "access": "public", + "declaration": "struct Point", + "location": "file://Sources/SwiftDemo/Demo.swift:9:14", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo5PointV1xSdvp", + "s:9SwiftDemo5PointV1ySdvp", + "s:9SwiftDemo5PointV1x1yACSd_Sdtcfc", + "s:9SwiftDemo5PointV11descriptionSSvp", + "s:9SwiftDemo5PointV6lengthSdvp" + ], + "conformances": [ + "s:s23CustomStringConvertibleP", + "s:s8CopyableP", + "s:s9EscapableP" + ] + }, + { + "id": "s:9SwiftDemo5PointV11descriptionSSvp", + "kind": "instanceProperty", + "path": "Point.description", + "name": "description", + "access": "public", + "declaration": "var description: String { get }", + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": false, + "extension": { + "extendedModule": "SwiftDemo", + "typeKind": "swift.struct" + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:9:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5PointV", + "sourceOrigin": "s:s23CustomStringConvertibleP11descriptionSSvp" + }, + { + "id": "s:9SwiftDemo5PointV1x1yACSd_Sdtcfc", + "kind": "initializer", + "path": "Point.init(x:y:)", + "name": "init(x:y:)", + "access": "public", + "declaration": "init(x: Double, y: Double)", + "parameters": [ + { + "label": "x", + "internalName": "x", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + }, + { + "label": "y", + "internalName": "y", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Demo.swift:12:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5PointV" + }, + { + "id": "s:9SwiftDemo5PointV1xSdvp", + "kind": "instanceProperty", + "path": "Point.x", + "name": "x", + "access": "public", + "declaration": "var x: Double", + "valueType": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Demo.swift:10:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5PointV" + }, + { + "id": "s:9SwiftDemo5PointV1ySdvp", + "kind": "instanceProperty", + "path": "Point.y", + "name": "y", + "access": "public", + "declaration": "var y: Double", + "valueType": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Demo.swift:11:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5PointV" + }, + { + "id": "s:9SwiftDemo5PointV6lengthSdvp", + "kind": "instanceProperty", + "path": "Point.length", + "name": "length", + "access": "public", + "declaration": "var length: Double { get }", + "valueType": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "settable": false, + "extension": { + "extendedModule": "SwiftDemo", + "typeKind": "swift.struct" + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:10:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5PointV" + }, + { + "id": "s:9SwiftDemo5ShapeP", + "kind": "protocol", + "path": "Shape", + "name": "Shape", + "access": "public", + "declaration": "protocol Shape : Greeter", + "location": "file://Sources/SwiftDemo/Shapes.swift:2:16", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo5ShapeP4areaSdvp", + "s:9SwiftDemo5ShapeP5sidesSivpZ" + ], + "conformances": [ + "s:9SwiftDemo7GreeterP" + ] + }, + { + "id": "s:9SwiftDemo5ShapeP4areaSdvp", + "kind": "instanceProperty", + "path": "Shape.area", + "name": "area", + "access": "public", + "declaration": "var area: Double { get }", + "protocolRequirement": true, + "valueType": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:3:8", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5ShapeP" + }, + { + "id": "s:9SwiftDemo5ShapeP5sidesSivpZ", + "kind": "typeProperty", + "path": "Shape.sides", + "name": "sides", + "access": "public", + "declaration": "static var sides: Int { get }", + "modifiers": [ + "static" + ], + "static": true, + "protocolRequirement": true, + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:4:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo5ShapeP" + }, + { + "id": "s:9SwiftDemo6CanvasC", + "kind": "class", + "path": "Canvas", + "name": "Canvas", + "access": "public", + "declaration": "@MainActor final class Canvas", + "attributes": [ + "@MainActor" + ], + "modifiers": [ + "final" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:101:19", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo6CanvasCACycfc", + "s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF" + ], + "conformances": [ + "s:s8SendableP" + ] + }, + { + "id": "s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF", + "kind": "instanceMethod", + "path": "Canvas.draw(_:)", + "name": "draw(_:)", + "access": "public", + "declaration": "@MainActor func draw(_ shape: any Shape)", + "attributes": [ + "@MainActor" + ], + "parameters": [ + { + "internalName": "shape", + "type": { + "spelling": "any Shape", + "references": [ + "s:9SwiftDemo5ShapeP" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:103:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6CanvasC" + }, + { + "id": "s:9SwiftDemo6CanvasCACycfc", + "kind": "initializer", + "path": "Canvas.init()", + "name": "init()", + "access": "public", + "declaration": "@MainActor init()", + "attributes": [ + "@MainActor" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:102:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6CanvasC" + }, + { + "id": "s:9SwiftDemo6FlavorO", + "kind": "enum", + "path": "Flavor", + "name": "Flavor", + "access": "public", + "declaration": "enum Flavor", + "location": "file://Sources/SwiftDemo/Demo.swift:15:12", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo6FlavorO7vanillayA2CmF", + "s:9SwiftDemo6FlavorO9chocolateyA2CmF", + "s:9SwiftDemo6FlavorO11descriptionSSvp", + "s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc", + "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO" + ], + "conformances": [ + "s:SH", + "s:SQ", + "s:SY", + "s:s23CustomStringConvertibleP", + "s:s8CopyableP", + "s:s9EscapableP" + ] + }, + { + "id": "s:9SwiftDemo6FlavorO11descriptionSSvp", + "kind": "instanceProperty", + "path": "Flavor.description", + "name": "description", + "access": "public", + "declaration": "var description: String { get }", + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": false, + "extension": { + "extendedModule": "SwiftDemo", + "typeKind": "swift.enum" + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:14:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO", + "sourceOrigin": "s:s23CustomStringConvertibleP11descriptionSSvp" + }, + { + "id": "s:9SwiftDemo6FlavorO7vanillayA2CmF", + "kind": "enumCase", + "path": "Flavor.vanilla", + "name": "vanilla", + "access": "public", + "declaration": "case vanilla", + "location": "file://Sources/SwiftDemo/Demo.swift:15:31", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO" + }, + { + "id": "s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc", + "kind": "initializer", + "path": "Flavor.init(rawValue:)", + "name": "init(rawValue:)", + "access": "public", + "declaration": "init?(rawValue: Int)", + "parameters": [ + { + "label": "rawValue", + "internalName": "rawValue", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "failable": true, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO", + "sourceOrigin": "s:SY8rawValuexSg03RawB0Qz_tcfc" + }, + { + "id": "s:9SwiftDemo6FlavorO9chocolateyA2CmF", + "kind": "enumCase", + "path": "Flavor.chocolate", + "name": "chocolate", + "access": "public", + "declaration": "case chocolate", + "location": "file://Sources/SwiftDemo/Demo.swift:15:44", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO" + }, + { + "id": "s:9SwiftDemo6LoaderC", + "kind": "class", + "path": "Loader", + "name": "Loader", + "access": "public", + "declaration": "final class Loader", + "modifiers": [ + "final" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:106:19", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo6LoaderCACycfc", + "s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF", + "s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF", + "s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF", + "s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF", + "s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF", + "s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF", + "s:9SwiftDemo6LoaderC4eachyyySiXEF", + "s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF", + "s:9SwiftDemo6LoaderC6updateyyAA5PointVzF", + "s:9SwiftDemo6LoaderC10modernOnlyyyF", + "s:9SwiftDemo6LoaderC11legacyFetchyyF", + "s:9SwiftDemo6LoaderC8oldFetchyyF" + ] + }, + { + "id": "s:9SwiftDemo6LoaderC10modernOnlyyyF", + "kind": "instanceMethod", + "path": "Loader.modernOnly()", + "name": "modernOnly()", + "access": "public", + "declaration": "func modernOnly()", + "availability": [ + { + "domain": "iOS", + "introduced": "16.0.0" + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:124:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC11legacyFetchyyF", + "kind": "instanceMethod", + "path": "Loader.legacyFetch()", + "name": "legacyFetch()", + "access": "public", + "declaration": "func legacyFetch()", + "availability": [ + { + "domain": "*", + "message": "Use fetch(url:) instead", + "unconditionallyDeprecated": true + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:127:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF", + "kind": "instanceMethod", + "path": "Loader.withCompletion(_:)", + "name": "withCompletion(_:)", + "access": "public", + "declaration": "func withCompletion(_ completion: @escaping (Result) -> Void)", + "parameters": [ + { + "internalName": "completion", + "type": { + "spelling": "(Result) -> Void", + "references": [ + "s:s6ResultO", + "s:SS", + "s:9SwiftDemo10ShapeErrorO", + "s:s4Voida" + ] + }, + "attributes": [ + "@escaping" + ] + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:116:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC4eachyyySiXEF", + "kind": "instanceMethod", + "path": "Loader.each(_:)", + "name": "each(_:)", + "access": "public", + "declaration": "func each(_ body: (Int) -> Void)", + "parameters": [ + { + "internalName": "body", + "type": { + "spelling": "(Int) -> Void", + "references": [ + "s:Si", + "s:s4Voida" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:117:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF", + "kind": "instanceMethod", + "path": "Loader.load(path:)", + "name": "load(path:)", + "access": "public", + "declaration": "func load(path: String) throws -> Data", + "parameters": [ + { + "label": "path", + "internalName": "path", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "returns": { + "spelling": "Data", + "references": [ + "s:10Foundation4DataV" + ] + }, + "throws": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:109:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF", + "kind": "instanceMethod", + "path": "Loader.wait(seconds:)", + "name": "wait(seconds:)", + "access": "public", + "declaration": "func wait(seconds: Double) async", + "parameters": [ + { + "label": "seconds", + "internalName": "seconds", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "async": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:111:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF", + "kind": "instanceMethod", + "path": "Loader.fetch(url:)", + "name": "fetch(url:)", + "access": "public", + "declaration": "func fetch(url: URL) async throws -> String", + "parameters": [ + { + "label": "url", + "internalName": "url", + "type": { + "spelling": "URL", + "references": [ + "s:10Foundation3URLV" + ] + } + } + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "async": true, + "throws": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:110:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF", + "kind": "instanceMethod", + "path": "Loader.first(of:)", + "name": "first(of:)", + "access": "public", + "declaration": "func first(of items: [Element]) -> Element?", + "parameters": [ + { + "label": "of", + "internalName": "items", + "type": { + "spelling": "[Element]", + "references": [ + "s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp" + ] + } + } + ], + "returns": { + "spelling": "Element?" + }, + "genericParameters": [ + { + "name": "Element", + "depth": 0, + "index": 0 + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:114:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF", + "kind": "instanceMethod", + "path": "Loader.lookup(table:key:)", + "name": "lookup(table:key:)", + "access": "public", + "declaration": "func lookup(table: [String : Int], key: String) -> Int?", + "parameters": [ + { + "label": "table", + "internalName": "table", + "type": { + "spelling": "[String : Int]", + "references": [ + "s:SS", + "s:Si" + ] + } + }, + { + "label": "key", + "internalName": "key", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "returns": { + "spelling": "Int?", + "references": [ + "s:Si" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:119:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC6updateyyAA5PointVzF", + "kind": "instanceMethod", + "path": "Loader.update(_:)", + "name": "update(_:)", + "access": "public", + "declaration": "func update(_ point: inout Point)", + "parameters": [ + { + "internalName": "point", + "type": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "modifier": "inout" + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:121:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC8oldFetchyyF", + "kind": "instanceMethod", + "path": "Loader.oldFetch()", + "name": "oldFetch()", + "access": "public", + "declaration": "func oldFetch()", + "availability": [ + { + "domain": "iOS", + "introduced": "15.0.0", + "deprecated": "17.0.0", + "renamed": "fetch(url:)" + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:130:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF", + "kind": "instanceMethod", + "path": "Loader.transform(_:)", + "name": "transform(_:)", + "access": "public", + "declaration": "func transform(_ shape: T) -> T where T : Shape", + "parameters": [ + { + "internalName": "shape", + "type": { + "spelling": "T", + "references": [ + "s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp" + ] + } + } + ], + "returns": { + "spelling": "T" + }, + "genericParameters": [ + { + "name": "T", + "depth": 0, + "index": 0 + } + ], + "genericConstraints": [ + { + "kind": "conformance", + "lhs": "T", + "rhs": "Shape", + "rhsPrecise": "s:9SwiftDemo5ShapeP" + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:113:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6LoaderCACycfc", + "kind": "initializer", + "path": "Loader.init()", + "name": "init()", + "access": "public", + "declaration": "init()", + "location": "file://Sources/SwiftDemo/Shapes.swift:107:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6LoaderC" + }, + { + "id": "s:9SwiftDemo6SquareC", + "kind": "class", + "path": "Square", + "name": "Square", + "access": "public", + "declaration": "final class Square", + "modifiers": [ + "final" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:34:19", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo6SquareC4sideSdvp", + "s:9SwiftDemo6SquareC4sideACSd_tcfc", + "s:9SwiftDemo6SquareC4areaSdvp", + "s:9SwiftDemo6SquareC5sidesSivpZ", + "s:9SwiftDemo6SquareC5greet4nameS2S_tF", + "s:9SwiftDemo6SquareC5scale2byySd_tF" + ], + "conformances": [ + "s:9SwiftDemo5ShapeP", + "s:9SwiftDemo7GreeterP" + ], + "superclass": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo6SquareC4areaSdvp", + "kind": "instanceProperty", + "path": "Square.area", + "name": "area", + "access": "public", + "declaration": "var area: Double { get }", + "valueType": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:42:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6SquareC", + "sourceOrigin": "s:9SwiftDemo5ShapeP4areaSdvp" + }, + { + "id": "s:9SwiftDemo6SquareC4sideACSd_tcfc", + "kind": "initializer", + "path": "Square.init(side:)", + "name": "init(side:)", + "access": "public", + "declaration": "init(side: Double)", + "parameters": [ + { + "label": "side", + "internalName": "side", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:37:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6SquareC" + }, + { + "id": "s:9SwiftDemo6SquareC4sideSdvp", + "kind": "instanceProperty", + "path": "Square.side", + "name": "side", + "access": "public", + "declaration": "var side: Double", + "valueType": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "settable": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:35:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6SquareC" + }, + { + "id": "s:9SwiftDemo6SquareC5greet4nameS2S_tF", + "kind": "instanceMethod", + "path": "Square.greet(name:)", + "name": "greet(name:)", + "access": "public", + "declaration": "func greet(name: String) -> String", + "parameters": [ + { + "label": "name", + "internalName": "name", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:44:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6SquareC", + "sourceOrigin": "s:9SwiftDemo7GreeterP5greet4nameS2S_tF" + }, + { + "id": "s:9SwiftDemo6SquareC5scale2byySd_tF", + "kind": "instanceMethod", + "path": "Square.scale(by:)", + "name": "scale(by:)", + "access": "public", + "declaration": "override func scale(by factor: Double)", + "modifiers": [ + "override" + ], + "parameters": [ + { + "label": "by", + "internalName": "factor", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:46:25", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6SquareC", + "overrides": "s:9SwiftDemo7PolygonC5scale2byySd_tF" + }, + { + "id": "s:9SwiftDemo6SquareC5sidesSivpZ", + "kind": "typeProperty", + "path": "Square.sides", + "name": "sides", + "access": "public", + "declaration": "static var sides: Int { get }", + "modifiers": [ + "static" + ], + "static": true, + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:43:22", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6SquareC", + "sourceOrigin": "s:9SwiftDemo5ShapeP5sidesSivpZ" + }, + { + "id": "s:9SwiftDemo7CounterC", + "kind": "actor", + "path": "Counter", + "name": "Counter", + "access": "public", + "declaration": "actor Counter", + "location": "file://Sources/SwiftDemo/Shapes.swift:90:13", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo7CounterC5valueSivp", + "s:9SwiftDemo7CounterCACycfc", + "s:9SwiftDemo7CounterC9incrementSiyF", + "s:9SwiftDemo7CounterC5labelSSyF", + "s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC" + ], + "conformances": [ + "s:ScA", + "s:s16SendableMetatypeP", + "s:s8SendableP" + ] + }, + { + "id": "s:9SwiftDemo7CounterC5labelSSyF", + "kind": "instanceMethod", + "path": "Counter.label()", + "name": "label()", + "access": "public", + "declaration": "nonisolated func label() -> String", + "attributes": [ + "nonisolated" + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:97:28", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC" + }, + { + "id": "s:9SwiftDemo7CounterC5valueSivp", + "kind": "instanceProperty", + "path": "Counter.value", + "name": "value", + "access": "public", + "declaration": "var value: Int { get }", + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:91:28", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC" + }, + { + "id": "s:9SwiftDemo7CounterC9incrementSiyF", + "kind": "instanceMethod", + "path": "Counter.increment()", + "name": "increment()", + "access": "public", + "declaration": "func increment() -> Int", + "returns": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:93:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC" + }, + { + "id": "s:9SwiftDemo7CounterCACycfc", + "kind": "initializer", + "path": "Counter.init()", + "name": "init()", + "access": "public", + "declaration": "init()", + "location": "file://Sources/SwiftDemo/Shapes.swift:92:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC" + }, + { + "id": "s:9SwiftDemo7GreeterP", + "kind": "protocol", + "path": "Greeter", + "name": "Greeter", + "access": "public", + "declaration": "protocol Greeter", + "location": "file://Sources/SwiftDemo/Demo.swift:0:16", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo7GreeterP5greet4nameS2S_tF" + ] + }, + { + "id": "s:9SwiftDemo7GreeterP5greet4nameS2S_tF", + "kind": "instanceMethod", + "path": "Greeter.greet(name:)", + "name": "greet(name:)", + "access": "public", + "declaration": "func greet(name: String) -> String", + "protocolRequirement": true, + "parameters": [ + { + "label": "name", + "internalName": "name", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "location": "file://Sources/SwiftDemo/Demo.swift:1:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7GreeterP" + }, + { + "id": "s:9SwiftDemo7PolygonC", + "kind": "class", + "path": "Polygon", + "name": "Polygon", + "access": "open", + "declaration": "class Polygon", + "location": "file://Sources/SwiftDemo/Shapes.swift:7:11", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo7PolygonC4nameSSvp", + "s:9SwiftDemo7PolygonC11vertexCountSivp", + "s:9SwiftDemo7PolygonC6sharedACvpZ", + "s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc", + "s:9SwiftDemo7PolygonC4nameACSgSS_tcfc", + "s:9SwiftDemo7PolygonC5scale2byySd_tF", + "s:9SwiftDemo7PolygonC5scale2byySi_tF", + "s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF", + "s:9SwiftDemo7PolygonC4makeACyFZ", + "s:9SwiftDemo7PolygonC8describeySSACSgFZ", + "s:9SwiftDemo7PolygonCyAA5PointVSicip" + ] + }, + { + "id": "s:9SwiftDemo7PolygonC11vertexCountSivp", + "kind": "instanceProperty", + "path": "Polygon.vertexCount", + "name": "vertexCount", + "access": "public", + "declaration": "var vertexCount: Int { get }", + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:9:28", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC4makeACyFZ", + "kind": "typeMethod", + "path": "Polygon.make()", + "name": "make()", + "access": "public", + "declaration": "class func make() -> Polygon", + "modifiers": [ + "class" + ], + "static": true, + "returns": { + "spelling": "Polygon", + "references": [ + "s:9SwiftDemo7PolygonC" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:26:22", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc", + "kind": "initializer", + "path": "Polygon.init(name:vertexCount:)", + "name": "init(name:vertexCount:)", + "access": "public", + "declaration": "init(name: String, vertexCount: Int)", + "parameters": [ + { + "label": "name", + "internalName": "name", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + }, + { + "label": "vertexCount", + "internalName": "vertexCount", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:12:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC4nameACSgSS_tcfc", + "kind": "initializer", + "path": "Polygon.init(name:)", + "name": "init(name:)", + "access": "public", + "declaration": "convenience init?(name: String)", + "modifiers": [ + "convenience" + ], + "parameters": [ + { + "label": "name", + "internalName": "name", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "failable": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:17:23", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC4nameSSvp", + "kind": "instanceProperty", + "path": "Polygon.name", + "name": "name", + "access": "public", + "declaration": "let name: String", + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": false, + "let": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:8:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF", + "kind": "instanceMethod", + "path": "Polygon.scale(x:y:)", + "name": "scale(x:y:)", + "access": "public", + "declaration": "func scale(x: Double, y: Double)", + "parameters": [ + { + "label": "x", + "internalName": "x", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + }, + { + "label": "y", + "internalName": "y", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:24:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC5scale2byySd_tF", + "kind": "instanceMethod", + "path": "Polygon.scale(by:)", + "name": "scale(by:)", + "access": "open", + "declaration": "func scale(by factor: Double)", + "parameters": [ + { + "label": "by", + "internalName": "factor", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:22:14", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC5scale2byySi_tF", + "kind": "instanceMethod", + "path": "Polygon.scale(by:)", + "name": "scale(by:)", + "access": "open", + "declaration": "func scale(by factor: Int)", + "parameters": [ + { + "label": "by", + "internalName": "factor", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:23:14", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC6sharedACvpZ", + "kind": "typeProperty", + "path": "Polygon.shared", + "name": "shared", + "access": "public", + "declaration": "static let shared: Polygon", + "modifiers": [ + "static" + ], + "static": true, + "valueType": { + "spelling": "Polygon", + "references": [ + "s:9SwiftDemo7PolygonC" + ] + }, + "settable": false, + "let": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:10:22", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonC8describeySSACSgFZ", + "kind": "typeMethod", + "path": "Polygon.describe(_:)", + "name": "describe(_:)", + "access": "public", + "declaration": "static func describe(_ polygon: Polygon?) -> String", + "modifiers": [ + "static" + ], + "static": true, + "parameters": [ + { + "internalName": "polygon", + "type": { + "spelling": "Polygon?", + "references": [ + "s:9SwiftDemo7PolygonC" + ] + } + } + ], + "returns": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "location": "file://Sources/SwiftDemo/Shapes.swift:27:23", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:9SwiftDemo7PolygonCyAA5PointVSicip", + "kind": "instanceSubscript", + "path": "Polygon.subscript(_:)", + "name": "subscript(_:)", + "access": "public", + "declaration": "subscript(index: Int) -> Point { get }", + "parameters": [ + { + "internalName": "index", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "returns": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "valueType": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Shapes.swift:29:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7PolygonC" + }, + { + "id": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "kind": "operator", + "path": "Flavor.!=(_:_:)", + "name": "!=(_:_:)", + "access": "public", + "declaration": "static func != (lhs: borrowing Self, rhs: borrowing Self) -> Bool", + "modifiers": [ + "static" + ], + "static": true, + "synthesized": true, + "parameters": [ + { + "internalName": "lhs", + "type": { + "spelling": "Self" + }, + "modifier": "borrowing" + }, + { + "internalName": "rhs", + "type": { + "spelling": "Self" + }, + "modifier": "borrowing" + } + ], + "returns": { + "spelling": "Bool", + "references": [ + "s:Sb" + ] + }, + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol" + }, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO", + "sourceOrigin": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ" + }, + { + "id": "s:SS9SwiftDemoE7shoutedSSvp", + "kind": "instanceProperty", + "path": "String.shouted", + "name": "shouted", + "access": "public", + "declaration": "var shouted: String { get }", + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": false, + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.struct" + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:18:15", + "graph": "SwiftDemo@Swift.symbols.json", + "parent": "s:SS" + }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "kind": "instanceProperty", + "path": "Flavor.hashValue", + "name": "hashValue", + "access": "public", + "declaration": "var hashValue: Int { get }", + "synthesized": true, + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol", + "constraints": [ + { + "kind": "conformance", + "lhs": "Self", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + }, + { + "kind": "conformance", + "lhs": "Self.RawValue", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ] + }, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO", + "sourceOrigin": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp" + }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "kind": "instanceMethod", + "path": "Flavor.hash(into:)", + "name": "hash(into:)", + "access": "public", + "declaration": "func hash(into hasher: inout Hasher)", + "synthesized": true, + "parameters": [ + { + "label": "into", + "internalName": "hasher", + "type": { + "spelling": "Hasher", + "references": [ + "s:s6HasherV" + ] + }, + "modifier": "inout" + } + ], + "genericConstraints": [ + { + "kind": "conformance", + "lhs": "Self", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + }, + { + "kind": "conformance", + "lhs": "Self.RawValue", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ], + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol", + "constraints": [ + { + "kind": "conformance", + "lhs": "Self", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + }, + { + "kind": "conformance", + "lhs": "Self.RawValue", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ] + }, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo6FlavorO", + "sourceOrigin": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF" + }, + { + "id": "s:Sa9SwiftDemoAA5PointVRszlE8centroidACyF", + "kind": "instanceMethod", + "path": "Array.centroid()", + "name": "centroid()", + "access": "public", + "declaration": "func centroid() -> Point", + "returns": { + "spelling": "Point", + "references": [ + "s:9SwiftDemo5PointV" + ] + }, + "genericParameters": [ + { + "name": "Element", + "depth": 0, + "index": 0 + } + ], + "genericConstraints": [ + { + "kind": "sameType", + "lhs": "Element", + "rhs": "Point", + "rhsPrecise": "s:9SwiftDemo5PointV" + } + ], + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.struct", + "constraints": [ + { + "kind": "sameType", + "lhs": "Element", + "rhs": "Point", + "rhsPrecise": "s:9SwiftDemo5PointV" + } + ] + }, + "location": "file://Sources/SwiftDemo/Extensions.swift:22:16", + "graph": "SwiftDemo@Swift.symbols.json", + "parent": "s:Sa" + }, + { + "id": "s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "kind": "instanceMethod", + "path": "Counter.assertIsolated(_:file:line:)", + "name": "assertIsolated(_:file:line:)", + "access": "public", + "declaration": "@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\nnonisolated func assertIsolated(_ message: @autoclosure () -> String = String(), file: StaticString = #fileID, line: UInt = #line)", + "attributes": [ + "@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)", + "nonisolated" + ], + "synthesized": true, + "parameters": [ + { + "internalName": "message", + "type": { + "spelling": "() -> String", + "references": [ + "s:SS" + ] + }, + "attributes": [ + "@autoclosure" + ], + "default": "String()" + }, + { + "label": "file", + "internalName": "file", + "type": { + "spelling": "StaticString", + "references": [ + "s:s12StaticStringV" + ] + }, + "default": "#fileID" + }, + { + "label": "line", + "internalName": "line", + "type": { + "spelling": "UInt", + "references": [ + "s:Su" + ] + }, + "default": "#line" + } + ], + "extension": { + "extendedModule": "_Concurrency", + "typeKind": "swift.protocol" + }, + "availability": [ + { + "domain": "iOS", + "introduced": "13.0.0" + }, + { + "domain": "macOS", + "introduced": "10.15.0" + }, + { + "domain": "tvOS", + "introduced": "13.0.0" + }, + { + "domain": "watchOS", + "introduced": "6.0.0" + } + ], + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC", + "sourceOrigin": "s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF" + }, + { + "id": "s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "kind": "instanceMethod", + "path": "Counter.assumeIsolated(_:file:line:)", + "name": "assumeIsolated(_:file:line:)", + "access": "public", + "declaration": "nonisolated func assumeIsolated(_ operation: (isolated Self) throws -> T, file: StaticString = #fileID, line: UInt = #line) rethrows -> T where T : Sendable", + "attributes": [ + "nonisolated" + ], + "synthesized": true, + "parameters": [ + { + "internalName": "operation", + "type": { + "spelling": "(isolated Self) throws -> T" + } + }, + { + "label": "file", + "internalName": "file", + "type": { + "spelling": "StaticString", + "references": [ + "s:s12StaticStringV" + ] + }, + "default": "#fileID" + }, + { + "label": "line", + "internalName": "line", + "type": { + "spelling": "UInt", + "references": [ + "s:Su" + ] + }, + "default": "#line" + } + ], + "returns": { + "spelling": "T" + }, + "throws": true, + "rethrows": true, + "genericParameters": [ + { + "name": "T", + "depth": 1, + "index": 0 + } + ], + "genericConstraints": [ + { + "kind": "conformance", + "lhs": "T", + "rhs": "Sendable", + "rhsPrecise": "s:s8SendableP" + } + ], + "extension": { + "extendedModule": "_Concurrency", + "typeKind": "swift.protocol" + }, + "availability": [ + { + "domain": "iOS", + "introduced": "13.0.0" + }, + { + "domain": "macOS", + "introduced": "10.15.0" + }, + { + "domain": "tvOS", + "introduced": "13.0.0" + }, + { + "domain": "watchOS", + "introduced": "6.0.0" + } + ], + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC", + "sourceOrigin": "s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF" + }, + { + "id": "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "kind": "instanceMethod", + "path": "Counter.withSerialExecutor(_:)", + "name": "withSerialExecutor(_:)", + "access": "public", + "declaration": "nonisolated func withSerialExecutor(_ operation: nonisolated(nonsending) (any SerialExecutor) async throws(E) -> T) async throws(E) -> T where E : Error, T : ~Copyable", + "attributes": [ + "nonisolated" + ], + "synthesized": true, + "parameters": [ + { + "internalName": "operation", + "type": { + "spelling": "nonisolated(nonsending) (any SerialExecutor) async throws(E) -> T", + "references": [ + "s:Scf" + ] + } + } + ], + "returns": { + "spelling": "T" + }, + "async": true, + "throws": true, + "thrownType": { + "spelling": "E" + }, + "genericParameters": [ + { + "name": "T", + "depth": 1, + "index": 0 + }, + { + "name": "E", + "depth": 1, + "index": 1 + } + ], + "genericConstraints": [ + { + "kind": "conformance", + "lhs": "E", + "rhs": "Error", + "rhsPrecise": "s:s5ErrorP" + } + ], + "extension": { + "extendedModule": "_Concurrency", + "typeKind": "swift.protocol" + }, + "availability": [ + { + "domain": "iOS", + "introduced": "13.0.0" + }, + { + "domain": "macOS", + "introduced": "10.15.0" + }, + { + "domain": "tvOS", + "introduced": "13.0.0" + }, + { + "domain": "watchOS", + "introduced": "6.0.0" + } + ], + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC", + "sourceOrigin": "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF" + }, + { + "id": "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "kind": "instanceMethod", + "path": "Counter.withSerialExecutor(_:)", + "name": "withSerialExecutor(_:)", + "access": "public", + "declaration": "nonisolated func withSerialExecutor(_ operation: (any SerialExecutor) throws(E) -> T) throws(E) -> T where E : Error, T : ~Copyable", + "attributes": [ + "nonisolated" + ], + "synthesized": true, + "parameters": [ + { + "internalName": "operation", + "type": { + "spelling": "(any SerialExecutor) throws(E) -> T", + "references": [ + "s:Scf" + ] + } + } + ], + "returns": { + "spelling": "T" + }, + "throws": true, + "thrownType": { + "spelling": "E" + }, + "genericParameters": [ + { + "name": "T", + "depth": 1, + "index": 0 + }, + { + "name": "E", + "depth": 1, + "index": 1 + } + ], + "genericConstraints": [ + { + "kind": "conformance", + "lhs": "E", + "rhs": "Error", + "rhsPrecise": "s:s5ErrorP" + } + ], + "extension": { + "extendedModule": "_Concurrency", + "typeKind": "swift.protocol" + }, + "availability": [ + { + "domain": "iOS", + "introduced": "13.0.0" + }, + { + "domain": "macOS", + "introduced": "10.15.0" + }, + { + "domain": "tvOS", + "introduced": "13.0.0" + }, + { + "domain": "watchOS", + "introduced": "6.0.0" + } + ], + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC", + "sourceOrigin": "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF" + }, + { + "id": "s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "kind": "instanceMethod", + "path": "Counter.preconditionIsolated(_:file:line:)", + "name": "preconditionIsolated(_:file:line:)", + "access": "public", + "declaration": "@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\nnonisolated func preconditionIsolated(_ message: @autoclosure () -> String = String(), file: StaticString = #fileID, line: UInt = #line)", + "attributes": [ + "@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)", + "nonisolated" + ], + "synthesized": true, + "parameters": [ + { + "internalName": "message", + "type": { + "spelling": "() -> String", + "references": [ + "s:SS" + ] + }, + "attributes": [ + "@autoclosure" + ], + "default": "String()" + }, + { + "label": "file", + "internalName": "file", + "type": { + "spelling": "StaticString", + "references": [ + "s:s12StaticStringV" + ] + }, + "default": "#fileID" + }, + { + "label": "line", + "internalName": "line", + "type": { + "spelling": "UInt", + "references": [ + "s:Su" + ] + }, + "default": "#line" + } + ], + "extension": { + "extendedModule": "_Concurrency", + "typeKind": "swift.protocol" + }, + "availability": [ + { + "domain": "iOS", + "introduced": "13.0.0" + }, + { + "domain": "macOS", + "introduced": "10.15.0" + }, + { + "domain": "tvOS", + "introduced": "13.0.0" + }, + { + "domain": "watchOS", + "introduced": "6.0.0" + } + ], + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7CounterC", + "sourceOrigin": "s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF" + }, + { + "id": "s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO", + "kind": "instanceProperty", + "path": "ShapeError.localizedDescription", + "name": "localizedDescription", + "access": "public", + "declaration": "var localizedDescription: String { get }", + "synthesized": true, + "valueType": { + "spelling": "String", + "references": [ + "s:SS" + ] + }, + "settable": false, + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol" + }, + "availability": [ + { + "domain": "iOS", + "introduced": "8.0.0" + }, + { + "domain": "macOS", + "introduced": "10.10.0" + }, + { + "domain": "tvOS", + "introduced": "9.0.0" + }, + { + "domain": "watchOS", + "introduced": "2.0.0" + } + ], + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo10ShapeErrorO", + "sourceOrigin": "s:s5ErrorP10FoundationE20localizedDescriptionSSvp" + } + ] +} diff --git a/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts b/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts new file mode 100644 index 000000000..1b0ee7e15 --- /dev/null +++ b/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts @@ -0,0 +1,16 @@ +// Generated from Swift symbol graphs for module SwiftDemo. +// Type-only: no Swift members are callable from JavaScript yet. + +interface Greeter {} +declare class Demo {} +declare class Point {} +declare class Flavor {} +interface Shape {} +declare class Polygon {} +declare class Square {} +declare class ShapeError {} +declare class Measurement {} +declare class Ring {} +declare class Counter {} +declare class Canvas {} +declare class Loader {} From 578784c952b4b89b72528cfa1287742313f980d3 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 20 Oct 2026 10:46:09 -0700 Subject: [PATCH 3/5] fix(metadata-generator): load SDK-scale Swift symbol graphs Running the loader over Apple SDK Swift modules (SwiftUI, Foundation, Charts, SwiftData, RegexBuilder, WeatherKit, Observation) surfaced declaration shapes the fixture did not cover and a memory blow-up. - Parse each symbol and relationship separately with a structural skimmer instead of building one llvm::json DOM per file. SwiftUI's 465 MB of graphs went from 23.5 GB peak RSS and 22.6 s to 1.2 GB and 6.9 s. - Parameter attributes before the label (`@ViewBuilder content:`) and attributes with argument or generic lists (`@attached(...)`, `@abi(func ...)`, `@KeyframesBuilder`) no longer derail parameter parsing. - Keep both symbols when Swift imports an Objective-C completion-handler method or property a second time as `async` under the same USR (`#async`), and when a subclass redeclares an Objective-C member (`#`), instead of dropping one as a duplicate. Membership edges attach only to the variant declared in the target type. - Record conformances a module adds to external types through extensions on the external type rather than reporting dangling relationships. - Record effects declared in accessor blocks (`{ get async }`). All seven modules now load without diagnostics. --- metadata-generator/src/Swift/SwiftIR.cpp | 1 + metadata-generator/src/Swift/SwiftIR.h | 9 +- .../src/Swift/SymbolGraphLoader.cpp | 528 ++++++++++++++---- .../src/Swift/SymbolGraphLoader.h | 3 + .../tests/swift/SymbolGraphLoaderTests.cpp | 144 ++++- 5 files changed, 574 insertions(+), 111 deletions(-) diff --git a/metadata-generator/src/Swift/SwiftIR.cpp b/metadata-generator/src/Swift/SwiftIR.cpp index 62d1171fd..92efeb593 100644 --- a/metadata-generator/src/Swift/SwiftIR.cpp +++ b/metadata-generator/src/Swift/SwiftIR.cpp @@ -317,6 +317,7 @@ std::string dumpModuleJSON(const Module& module) { writeNonEmpty(out, "extendedModule", external.extendedModule); writeNonEmpty(out, "typeKind", external.typeKind); writeStringArray(out, "members", external.memberIds); + writeStringArray(out, "conformances", external.conformances); }); } }); diff --git a/metadata-generator/src/Swift/SwiftIR.h b/metadata-generator/src/Swift/SwiftIR.h index b77f67edb..4ebc68641 100644 --- a/metadata-generator/src/Swift/SwiftIR.h +++ b/metadata-generator/src/Swift/SwiftIR.h @@ -137,7 +137,11 @@ struct Relationship { }; struct Symbol { + // Canonical identifier: the USR, except for the `async` variant Swift + // imports for an Objective-C completion-handler method, which shares the + // method's USR and is keyed `#async`. std::string preciseId; + std::string usr; SymbolKind kind = SymbolKind::Unknown; std::string kindIdentifier; std::vector pathComponents; @@ -184,7 +188,8 @@ struct Symbol { std::vector genericConstraints; std::optional extension; std::vector availability; - std::vector docComment; + // Doc comment lines joined with '\n'. + std::string docComment; std::optional location; // Graph file the symbol was read from, relative to the scanned directory. std::string sourceGraph; @@ -210,6 +215,8 @@ struct ExternalType { std::string extendedModule; std::string typeKind; std::vector memberIds; + // Protocols this module makes the type conform to through extensions. + std::vector conformances; }; struct Platform { diff --git a/metadata-generator/src/Swift/SymbolGraphLoader.cpp b/metadata-generator/src/Swift/SymbolGraphLoader.cpp index e30f08ffb..4b4d63469 100644 --- a/metadata-generator/src/Swift/SymbolGraphLoader.cpp +++ b/metadata-generator/src/Swift/SymbolGraphLoader.cpp @@ -1,5 +1,6 @@ #include "SymbolGraphLoader.h" +#include #include #include #include @@ -112,12 +113,20 @@ Tokens tokenize(const Fragments& fragments) { } llvm::StringRef text = fragment.spelling; - // Attributes with arguments (e.g. "@backDeployed(before: iOS 17.0)\n") are - // emitted as plain text rather than as attribute fragments. + // Some attributes arrive as plain text ("@backDeployed(before: iOS + // 17.0)\n", "@abi(func f(...))"). Only the name becomes the attribute + // token; its argument list is tokenized normally so consumeAttribute can + // match the parentheses, which may close in a later fragment. if (text.ltrim().startswith("@")) { - tokens.push_back( - Token{Token::Type::Fragment, "attribute", text.trim().str(), ""}); - continue; + llvm::StringRef rest = text.ltrim(); + size_t nameEnd = 1; + while (nameEnd < rest.size() && + (llvm::isAlnum(rest[nameEnd]) || rest[nameEnd] == '_')) { + nameEnd++; + } + tokens.push_back(Token{Token::Type::Fragment, "attribute", + rest.take_front(nameEnd).str(), ""}); + text = rest.drop_front(nameEnd); } size_t i = 0; @@ -296,6 +305,32 @@ class DeclarationParser { } } + // Returns the attribute at `index` together with an argument list that + // follows it directly (`@attached(peer, names: ...)`), advancing `index` + // past both. + std::string consumeAttribute(size_t& index, size_t end) const { + llvm::StringRef text = _tokens[index].text; + std::string attribute = text.trim().str(); + index++; + // "@autoclosure " carries its separator inside the fragment; a following + // '(' then starts the attributed type, not an argument list. + bool abuts = !text.empty() && !llvm::isSpace(text.back()); + if (abuts && index < end && + (_tokens[index].isPunct('(') || _tokens[index].isPunct('<'))) { + int depth = 0; + while (index < end) { + const Token& token = _tokens[index++]; + attribute += token.text; + if (opens(token)) { + depth++; + } else if (closes(token) && --depth == 0) { + break; + } + } + } + return attribute; + } + void skipBalanced() { int depth = 0; while (!atEnd()) { @@ -328,7 +363,8 @@ class DeclarationParser { while (!atEnd()) { const Token& token = _tokens[_pos]; if (token.isFragment("attribute")) { - _symbol.attributes.push_back(llvm::StringRef(token.text).trim().str()); + _symbol.attributes.push_back(consumeAttribute(_pos, _tokens.size())); + continue; } else if (isIntroKeyword(token)) { _intro = token.text; _pos++; @@ -396,8 +432,18 @@ class DeclarationParser { } Parameter parameter; + // Parameter attributes (result builders, property wrappers) precede the + // argument label: `@ViewBuilder content: () -> Content`. + while (begin < end && (_tokens[begin].isFragment("attribute") || + _tokens[begin].type == Token::Type::Space)) { + if (_tokens[begin].type == Token::Type::Space) { + begin++; + } else { + parameter.attributes.push_back(consumeAttribute(begin, end)); + } + } bool hasExternal = false; - if (_tokens[begin].isFragment("externalParam")) { + if (begin < end && _tokens[begin].isFragment("externalParam")) { hasExternal = true; parameter.label = _tokens[begin].text == "_" ? "" : _tokens[begin].text; parameter.internalName = parameter.label; @@ -444,9 +490,7 @@ class DeclarationParser { if (token.type == Token::Type::Space) { begin++; } else if (token.isFragment("attribute")) { - parameter.attributes.push_back( - llvm::StringRef(token.text).trim().str()); - begin++; + parameter.attributes.push_back(consumeAttribute(begin, typeEnd)); } else if (token.isFragment("keyword") && modifiers.count(token.text)) { parameter.modifier = token.text; begin++; @@ -508,8 +552,13 @@ class DeclarationParser { return; } while (!atEnd() && !_tokens[_pos].isPunct('}')) { - if (_tokens[_pos].isKeyword("set")) { + const Token& token = _tokens[_pos]; + if (token.isKeyword("set")) { _symbol.isSettable = true; + } else if (token.isKeyword("async")) { + _symbol.isAsync = true; + } else if (token.isKeyword("throws")) { + _symbol.isThrowing = true; } _pos++; } @@ -635,7 +684,8 @@ std::optional parseSymbol(const Object& object, const std::string& graphName, std::vector& diagnostics) { Symbol symbol; - symbol.preciseId = str(object.getObject("identifier"), "precise"); + symbol.usr = str(object.getObject("identifier"), "precise"); + symbol.preciseId = symbol.usr; if (symbol.preciseId.empty()) { report(diagnostics, Severity::Warning, "missing-field", "symbol without identifier.precise skipped", graphName); @@ -696,7 +746,10 @@ std::optional parseSymbol(const Object& object, if (const Object* doc = object.getObject("docComment")) { if (const Array* lines = doc->getArray("lines")) { for (const auto& line : *lines) { - symbol.docComment.push_back(str(line.getAsObject(), "text")); + if (!symbol.docComment.empty()) { + symbol.docComment += '\n'; + } + symbol.docComment += str(line.getAsObject(), "text"); } } } @@ -813,59 +866,94 @@ void resolve(Module& module, std::vector& diagnostics) { }; for (const auto& relationship : module.relationships) { - auto sourceIt = module.symbols.find(relationship.source); - if (sourceIt == module.symbols.end()) { - report(diagnostics, Severity::Warning, "dangling-relationship", - relationship.kind + " relationship from unknown symbol '" + - relationship.source + "'", - module.name, relationship.source); - continue; - } - Symbol& source = sourceIt->second; const std::string& kind = relationship.kind; - if (kind == "memberOf" || kind == "requirementOf" || - kind == "optionalRequirementOf") { - source.parentId = relationship.target; - if (!relationship.sourceOriginId.empty()) { - source.sourceOriginId = relationship.sourceOriginId; - source.sourceOriginName = relationship.sourceOriginName; + // A relationship names a USR, which every variant keyed by it shares + // (see insertSymbol). Membership applies only to the variant declared + // in the target type. + std::vector sources; + const Symbol* target = module.find(relationship.target); + bool isMembership = kind == "memberOf" || kind == "requirementOf" || + kind == "optionalRequirementOf"; + for (auto it = module.symbols.lower_bound(relationship.source); + it != module.symbols.end() && + llvm::StringRef(it->first).startswith(relationship.source); + ++it) { + Symbol& candidate = it->second; + if (candidate.usr != relationship.source) { + continue; } - if (kind != "memberOf") { - source.isProtocolRequirement = true; - source.isOptionalRequirement = kind == "optionalRequirementOf"; + if (isMembership && target && !candidate.pathComponents.empty() && + !std::equal(target->pathComponents.begin(), + target->pathComponents.end(), + candidate.pathComponents.begin(), + candidate.pathComponents.end() - 1)) { + continue; } + sources.push_back(&candidate); + } - auto targetIt = module.symbols.find(relationship.target); - if (targetIt != module.symbols.end()) { - targetIt->second.memberIds.push_back(source.preciseId); + if (sources.empty()) { + // Conformances this module's extensions add to external types + // (`extension Array: DataProtocol where Element == UInt8`). + if (kind == "conformsTo" || kind == "inheritsFrom") { + ExternalType& external = module.externalTypes[relationship.source]; + external.preciseId = relationship.source; + external.conformances.push_back(relationship.target); + rememberExternal(relationship); continue; } - rememberExternal(relationship); - ExternalType& external = module.externalTypes[relationship.target]; - external.preciseId = relationship.target; - external.qualifiedName = module.externalNames[relationship.target]; - if (source.extension) { - external.extendedModule = source.extension->extendedModule; - external.typeKind = source.extension->typeKind; - } - external.memberIds.push_back(source.preciseId); - } else if (kind == "conformsTo") { - source.conformances.push_back(relationship.target); - rememberExternal(relationship); - } else if (kind == "inheritsFrom") { - if (source.kind == SymbolKind::Protocol) { + report(diagnostics, Severity::Warning, "dangling-relationship", + kind + " relationship from unknown symbol '" + + relationship.source + "'", + module.name, relationship.source); + continue; + } + + for (Symbol* sourcePtr : sources) { + Symbol& source = *sourcePtr; + if (kind == "memberOf" || kind == "requirementOf" || + kind == "optionalRequirementOf") { + source.parentId = relationship.target; + if (!relationship.sourceOriginId.empty()) { + source.sourceOriginId = relationship.sourceOriginId; + source.sourceOriginName = relationship.sourceOriginName; + } + if (kind != "memberOf") { + source.isProtocolRequirement = true; + source.isOptionalRequirement = kind == "optionalRequirementOf"; + } + + auto targetIt = module.symbols.find(relationship.target); + if (targetIt != module.symbols.end()) { + targetIt->second.memberIds.push_back(source.preciseId); + continue; + } + rememberExternal(relationship); + ExternalType& external = module.externalTypes[relationship.target]; + external.preciseId = relationship.target; + if (source.extension) { + external.extendedModule = source.extension->extendedModule; + external.typeKind = source.extension->typeKind; + } + external.memberIds.push_back(source.preciseId); + } else if (kind == "conformsTo") { source.conformances.push_back(relationship.target); - } else { - source.superclassId = relationship.target; + rememberExternal(relationship); + } else if (kind == "inheritsFrom") { + if (source.kind == SymbolKind::Protocol) { + source.conformances.push_back(relationship.target); + } else { + source.superclassId = relationship.target; + } + rememberExternal(relationship); + } else if (kind == "overrides") { + source.overriddenId = relationship.target; + rememberExternal(relationship); + } else if (kind == "defaultImplementationOf") { + source.defaultImplementationOf.push_back(relationship.target); + rememberExternal(relationship); } - rememberExternal(relationship); - } else if (kind == "overrides") { - source.overriddenId = relationship.target; - rememberExternal(relationship); - } else if (kind == "defaultImplementationOf") { - source.defaultImplementationOf.push_back(relationship.target); - rememberExternal(relationship); } } @@ -883,12 +971,162 @@ void resolve(Module& module, std::vector& diagnostics) { } } for (auto& entry : module.externalTypes) { - sortBySourceOrder(entry.second.memberIds, module); + ExternalType& external = entry.second; + sortBySourceOrder(external.memberIds, module); + std::sort(external.conformances.begin(), external.conformances.end()); + external.conformances.erase( + std::unique(external.conformances.begin(), external.conformances.end()), + external.conformances.end()); + // Graphs name a relationship's target, never its source; an extended + // type's name is only known when some relationship targets it. + auto name = module.externalNames.find(external.preciseId); + external.qualifiedName = + name != module.externalNames.end() ? name->second : external.preciseId; } sortBySourceOrder(module.topLevelIds, module); std::sort(module.graphFiles.begin(), module.graphFiles.end()); } +// Structural scan of JSON text that locates object members and array +// elements without building a DOM. Whole SDK graphs run to hundreds of MB, and +// an llvm::json DOM of one costs tens of GB, so the loader skims the top level +// and parses each symbol and relationship on its own. +namespace JsonSkimmer { + +size_t skipSpace(llvm::StringRef text, size_t i) { + while (i < text.size() && llvm::isSpace(text[i])) { + i++; + } + return i; +} + +// Index one past the value starting at `i`, or npos. +size_t skipValue(llvm::StringRef text, size_t i) { + if (i >= text.size()) { + return llvm::StringRef::npos; + } + char c = text[i]; + if (c == '"') { + for (i++; i < text.size(); i++) { + if (text[i] == '\\') { + i++; + } else if (text[i] == '"') { + return i + 1; + } + } + return llvm::StringRef::npos; + } + if (c == '{' || c == '[') { + int depth = 0; + for (; i < text.size(); i++) { + char d = text[i]; + if (d == '"') { + size_t end = skipValue(text, i); + if (end == llvm::StringRef::npos) { + return end; + } + i = end - 1; + } else if (d == '{' || d == '[') { + depth++; + } else if ((d == '}' || d == ']') && --depth == 0) { + return i + 1; + } + } + return llvm::StringRef::npos; + } + size_t start = i; + while (i < text.size() && !llvm::isSpace(text[i]) && + !llvm::StringRef(",}]").contains(text[i])) { + i++; + } + return i == start ? llvm::StringRef::npos : i; +} + +bool fail(std::string& error, const char* what, size_t offset) { + error = std::string(what) + " at offset " + std::to_string(offset); + return false; +} + +bool objectMembers( + llvm::StringRef text, + std::vector>& members, + std::string& error) { + size_t i = skipSpace(text, 0); + if (i >= text.size() || text[i] != '{') { + return fail(error, "expected '{'", i); + } + i = skipSpace(text, i + 1); + if (i < text.size() && text[i] == '}') { + i++; + } else { + while (true) { + i = skipSpace(text, i); + size_t keyEnd = skipValue(text, i); + if (i >= text.size() || text[i] != '"' || + keyEnd == llvm::StringRef::npos) { + return fail(error, "expected member name", i); + } + llvm::StringRef key = text.slice(i + 1, keyEnd - 1); + i = skipSpace(text, keyEnd); + if (i >= text.size() || text[i] != ':') { + return fail(error, "expected ':'", i); + } + i = skipSpace(text, i + 1); + size_t valueEnd = skipValue(text, i); + if (valueEnd == llvm::StringRef::npos) { + return fail(error, "malformed value", i); + } + members.emplace_back(key, text.slice(i, valueEnd)); + i = skipSpace(text, valueEnd); + if (i < text.size() && text[i] == ',') { + i++; + continue; + } + if (i < text.size() && text[i] == '}') { + i++; + break; + } + return fail(error, "expected ',' or '}'", i); + } + } + if (skipSpace(text, i) != text.size()) { + return fail(error, "trailing content", i); + } + return true; +} + +bool arrayElements(llvm::StringRef text, + llvm::function_ref visit, + std::string& error) { + size_t i = skipSpace(text, 0); + if (i >= text.size() || text[i] != '[') { + return fail(error, "expected '['", i); + } + i = skipSpace(text, i + 1); + if (i < text.size() && text[i] == ']') { + return true; + } + while (true) { + i = skipSpace(text, i); + size_t end = skipValue(text, i); + if (end == llvm::StringRef::npos) { + return fail(error, "malformed element", i); + } + visit(text.slice(i, end)); + i = skipSpace(text, end); + if (i < text.size() && text[i] == ',') { + i++; + continue; + } + if (i < text.size() && text[i] == ']') { + return true; + } + return fail(error, "expected ',' or ']'", i); + } +} + +} // namespace JsonSkimmer + } // namespace std::vector SymbolGraphLoader::findGraphFiles( @@ -931,20 +1169,44 @@ void SymbolGraphLoader::addFile(const std::string& filePath, void SymbolGraphLoader::addBuffer(llvm::StringRef json, const std::string& displayName) { - auto parsed = llvm::json::parse(json); - if (!parsed) { - report(_diagnostics, Severity::Error, "invalid-json", - llvm::toString(parsed.takeError()), displayName); + std::vector> members; + std::string error; + if (!JsonSkimmer::objectMembers(json, members, error)) { + report(_diagnostics, Severity::Error, "invalid-json", error, displayName); return; } - const Object* root = parsed->getAsObject(); - if (!root) { - report(_diagnostics, Severity::Error, "invalid-json", - "symbol graph root is not an object", displayName); - return; + llvm::StringRef metadataText, moduleText, symbolsText, relationshipsText; + for (const auto& member : members) { + if (member.first == "metadata") { + metadataText = member.second; + } else if (member.first == "module") { + moduleText = member.second; + } else if (member.first == "symbols") { + symbolsText = member.second; + } else if (member.first == "relationships") { + relationshipsText = member.second; + } } - const Object* metadata = root->getObject("metadata"); + auto parseSection = + [&](llvm::StringRef text, + llvm::StringRef name) -> std::optional { + if (text.empty()) { + return std::nullopt; + } + auto value = llvm::json::parse(text); + if (!value) { + report(_diagnostics, Severity::Error, "invalid-json", + name.str() + ": " + llvm::toString(value.takeError()), + displayName); + return std::nullopt; + } + return std::move(*value); + }; + + auto metadataValue = parseSection(metadataText, "metadata"); + const Object* metadata = + metadataValue ? metadataValue->getAsObject() : nullptr; auto format = version(metadata ? metadata->getObject("formatVersion") : nullptr); if (!format) { @@ -967,7 +1229,9 @@ void SymbolGraphLoader::addBuffer(llvm::StringRef json, displayName); } - const Object* moduleObject = root->getObject("module"); + auto moduleValue = parseSection(moduleText, "module"); + const Object* moduleObject = + moduleValue ? moduleValue->getAsObject() : nullptr; std::string moduleName = str(moduleObject, "name"); if (moduleName.empty()) { report(_diagnostics, Severity::Error, "missing-field", @@ -999,45 +1263,101 @@ void SymbolGraphLoader::addBuffer(llvm::StringRef json, } module.graphFiles.push_back(displayName); - if (const Array* symbols = root->getArray("symbols")) { - for (const auto& value : *symbols) { - const Object* object = value.getAsObject(); - if (!object) { - continue; - } - auto symbol = parseSymbol(*object, displayName, _diagnostics); - if (!symbol) { - continue; - } - auto existing = module.symbols.find(symbol->preciseId); - if (existing != module.symbols.end()) { - if (existing->second.declarationText != symbol->declarationText) { - report(_diagnostics, Severity::Warning, "duplicate-symbol", - "symbol declared differently in '" + - existing->second.sourceGraph + "' and '" + displayName + - "'; keeping the first", - displayName, symbol->preciseId); - } - continue; - } - std::string id = symbol->preciseId; - module.symbols.emplace(std::move(id), std::move(*symbol)); + // Elements are parsed one at a time; see JsonSkimmer. + auto forEachObject = [&](llvm::StringRef arrayText, llvm::StringRef name, + llvm::function_ref visit) { + if (arrayText.empty()) { + return; } - } + std::string arrayError; + bool ok = JsonSkimmer::arrayElements( + arrayText, + [&](llvm::StringRef element) { + auto value = llvm::json::parse(element); + if (!value) { + report(_diagnostics, Severity::Error, "invalid-json", + name.str() + ": " + llvm::toString(value.takeError()), + displayName); + return; + } + if (const Object* object = value->getAsObject()) { + visit(*object); + } + }, + arrayError); + if (!ok) { + report(_diagnostics, Severity::Error, "invalid-json", + name.str() + ": " + arrayError, displayName); + } + }; - if (const Array* relationships = root->getArray("relationships")) { - for (const auto& value : *relationships) { - const Object* object = value.getAsObject(); - if (!object) { - continue; - } - const Object* origin = object->getObject("sourceOrigin"); - module.relationships.push_back( - Relationship{str(object, "kind"), str(object, "source"), - str(object, "target"), str(object, "targetFallback"), - str(origin, "identifier"), str(origin, "displayName")}); + forEachObject(symbolsText, "symbols", [&](const Object& object) { + auto symbol = parseSymbol(object, displayName, _diagnostics); + if (symbol) { + insertSymbol(module, std::move(*symbol), displayName); } + }); + + forEachObject(relationshipsText, "relationships", [&](const Object& object) { + const Object* origin = object.getObject("sourceOrigin"); + module.relationships.push_back( + Relationship{str(&object, "kind"), str(&object, "source"), + str(&object, "target"), str(&object, "targetFallback"), + str(origin, "identifier"), str(origin, "displayName")}); + }); +} + +void SymbolGraphLoader::insertSymbol(Module& module, Symbol symbol, + const std::string& displayName) { + auto existing = module.symbols.find(symbol.preciseId); + if (existing == module.symbols.end()) { + std::string id = symbol.preciseId; + module.symbols.emplace(std::move(id), std::move(symbol)); + return; + } + Symbol& other = existing->second; + if (other.declarationText == symbol.declarationText && + other.pathComponents == symbol.pathComponents) { + return; + } + auto ownerOf = [](const Symbol& s) { + return std::vector(s.pathComponents.begin(), + s.pathComponents.empty() + ? s.pathComponents.end() + : s.pathComponents.end() - 1); + }; + if (ownerOf(other) != ownerOf(symbol)) { + // An Objective-C method redeclared by a subclass (NSMutableArray's + // settable subscript) keeps the superclass method's USR. The variant + // whose path sorts first keeps the plain USR; others are keyed by owner. + if (symbol.pathComponents < other.pathComponents) { + std::swap(other, symbol); + } + symbol.preciseId = symbol.usr + "#" + llvm::join(ownerOf(symbol), "."); + if (!module.symbols.count(symbol.preciseId)) { + std::string id = symbol.preciseId; + module.symbols.emplace(std::move(id), std::move(symbol)); + } + return; + } + if (other.isAsync != symbol.isAsync) { + // Swift imports an Objective-C completion-handler method twice, as the + // original and as an `async` variant, under the same USR. Keep both; the + // original keeps the plain USR. + if (!symbol.isAsync) { + std::swap(other, symbol); + } + symbol.preciseId = symbol.usr + "#async"; + if (!module.symbols.count(symbol.preciseId)) { + std::string id = symbol.preciseId; + module.symbols.emplace(std::move(id), std::move(symbol)); + } + return; } + report(_diagnostics, Severity::Warning, "duplicate-symbol", + "symbol declared differently in '" + other.sourceGraph + "' and '" + + displayName + "'; keeping the first", + displayName, symbol.preciseId); } ModuleSet SymbolGraphLoader::finish() { diff --git a/metadata-generator/src/Swift/SymbolGraphLoader.h b/metadata-generator/src/Swift/SymbolGraphLoader.h index 5058cb28b..75d21607d 100644 --- a/metadata-generator/src/Swift/SymbolGraphLoader.h +++ b/metadata-generator/src/Swift/SymbolGraphLoader.h @@ -37,6 +37,9 @@ class SymbolGraphLoader { ModuleSet finish(); private: + void insertSymbol(Module& module, Symbol symbol, + const std::string& displayName); + std::map _modules; std::vector _diagnostics; }; diff --git a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp index d8e0e042e..8d80bc582 100644 --- a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp +++ b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp @@ -87,13 +87,20 @@ std::string graphJSON(const std::string& symbols, symbols + R"(],"relationships":[)" + relationships + "]}"; } +// `owner` is the dot-separated path of the containing type, if any. std::string symbolJSON(const std::string& id, const std::string& kind, - const std::string& path, - const std::string& declaration) { - return R"({"kind":{"identifier":")" + kind + - R"("},"identifier":{"precise":")" + id + R"("},"pathComponents":[")" + - path + - R"("],"names":{"title":"x"},"accessLevel":"public","declarationFragments":[)" + + const std::string& name, const std::string& declaration, + const std::string& owner = "") { + std::string path; + for (llvm::StringRef rest = owner; !rest.empty();) { + auto split = rest.split('.'); + path += "\"" + split.first.str() + "\","; + rest = split.second; + } + path += "\"" + name + "\""; + return R"({"kind":{"identifier":")" + kind + R"("},"identifier":{"precise":")" + + id + R"("},"pathComponents":[)" + path + + R"(],"names":{"title":"x"},"accessLevel":"public","declarationFragments":[)" + declaration + "]}"; } @@ -606,6 +613,131 @@ TEST(ConflictingDuplicateSymbolsAreReported) { CHECK(identical.diagnostics.empty()); } +TEST(AsyncImportVariantsAreBothKept) { + // Swift imports an Objective-C completion-handler method twice under one + // USR: as written and as an `async` variant. + std::string usr = "c:objc(cs)Mini(im)loadWithCompletion:"; + std::string type = symbolJSON( + "c:objc(cs)Mini", "swift.class", "Mini", + R"json({"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Mini"})json"); + std::string callback = symbolJSON( + usr, "swift.method", "load(completion:)", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" () -> "},{"kind":"typeIdentifier","spelling":"Void"},{"kind":"text","spelling":")"})json", + "Mini"); + std::string async = symbolJSON( + usr, "swift.method", "load()", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"() "},{"kind":"keyword","spelling":"async"})json", + "Mini"); + std::string relationship = R"({"kind":"memberOf","source":")" + usr + + R"(","target":"c:objc(cs)Mini"})"; + + for (bool asyncFirst : {false, true}) { + std::string symbols = type + "," + (asyncFirst ? async + "," + callback + : callback + "," + async); + ModuleSet set = loadBuffers( + {{"mini.symbols.json", graphJSON(symbols, relationship)}}); + CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); + REQUIRE(set.modules.count("Mini")); + const Module& module = set.modules.at("Mini"); + const Symbol* original = module.find(usr); + const Symbol* variant = module.find(usr + "#async"); + REQUIRE(original && variant); + CHECK(!original->isAsync); + CHECK(variant->isAsync); + CHECK_EQ(variant->usr, usr); + CHECK_EQ(variant->name, std::string("load()")); + CHECK_EQ(memberNames(module, *module.find("c:objc(cs)Mini")).size(), + size_t(2)); + } +} + +TEST(SubclassRedeclarationsAreKeyedByOwner) { + // NSMutableArray redeclares NSArray's subscript (adding a setter) under the + // same USR. + std::string usr = "c:objc(cs)NSArray(im)objectAtIndexedSubscript:"; + auto type = [](const std::string& name) { + return symbolJSON( + "c:objc(cs)" + name, "swift.class", name, + R"json({"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":")json" + + name + R"json("})json"); + }; + auto subscript = [&](const std::string& owner, const std::string& accessors) { + return symbolJSON( + usr, "swift.subscript", "subscript(_:)", + R"json({"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"idx"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int"},{"kind":"text","spelling":") -> "},{"kind":"keyword","spelling":"Any"},{"kind":"text","spelling":" { "},)json" + + accessors + R"json({"kind":"text","spelling":" }"})json", + owner); + }; + std::string base = subscript("NSArray", R"json({"kind":"keyword","spelling":"get"},)json"); + std::string mutableVariant = subscript( + "NSMutableArray", + R"json({"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"set"},)json"); + std::string relationships = + R"({"kind":"memberOf","source":")" + usr + + R"(","target":"c:objc(cs)NSArray"},{"kind":"memberOf","source":")" + usr + + R"(","target":"c:objc(cs)NSMutableArray"})"; + + for (bool mutableFirst : {false, true}) { + std::string symbols = type("NSArray") + "," + type("NSMutableArray") + "," + + (mutableFirst ? mutableVariant + "," + base + : base + "," + mutableVariant); + ModuleSet set = loadBuffers( + {{"mini.symbols.json", graphJSON(symbols, relationships)}}); + CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); + REQUIRE(set.modules.count("Mini")); + const Module& module = set.modules.at("Mini"); + const Symbol* plain = module.find(usr); + const Symbol* owned = module.find(usr + "#NSMutableArray"); + REQUIRE(plain && owned); + CHECK(!plain->isSettable); + CHECK(owned->isSettable); + CHECK_EQ(plain->parentId, std::string("c:objc(cs)NSArray")); + CHECK_EQ(owned->parentId, std::string("c:objc(cs)NSMutableArray")); + CHECK_EQ(module.find("c:objc(cs)NSArray")->memberIds.size(), size_t(1)); + CHECK_EQ(module.find("c:objc(cs)NSMutableArray")->memberIds.size(), + size_t(1)); + } +} + +TEST(ExternalConformancesAreRecorded) { + std::string relationship = + R"({"kind":"conformsTo","source":"s:Sa","target":"s:4Mini1PP"},)" + R"({"kind":"memberOf","source":"s:4Mini1fyyF","target":"s:Sa","targetFallback":"Swift.Array"})"; + std::string member = symbolJSON( + "s:4Mini1fyyF", "swift.method", "f()", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"f"},{"kind":"text","spelling":"()"})json"); + ModuleSet set = + loadBuffers({{"mini.symbols.json", graphJSON(member, relationship)}}); + CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); + REQUIRE(set.modules.count("Mini")); + const auto& externals = set.modules.at("Mini").externalTypes; + REQUIRE(externals.count("s:Sa")); + CHECK_EQ(externals.at("s:Sa").qualifiedName, std::string("Swift.Array")); + CHECK_EQ(llvm::join(externals.at("s:Sa").conformances, ","), + std::string("s:4Mini1PP")); +} + +TEST(SkimmerHandlesStringsAndNesting) { + // Braces, brackets and escaped quotes inside strings must not affect the + // structural scan. + std::string symbol = symbolJSON( + "s:4Mini1fyyF", "swift.func", "f()", + R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"f"},{"kind":"text","spelling":"()"})json"); + symbol.insert(symbol.size() - 1, + R"json(,"docComment":{"lines":[{"text":"a } ] { [ \"quoted\" \\"}]})json"); + ModuleSet set = loadBuffers({{"mini.symbols.json", graphJSON(symbol, "")}}); + CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); + REQUIRE(set.modules.count("Mini")); + const Symbol* f = set.modules.at("Mini").find("s:4Mini1fyyF"); + REQUIRE(f); + CHECK_EQ(f->docComment, std::string("a } ] { [ \"quoted\" \\")); + + ModuleSet trailing = + loadBuffers({{"mini.symbols.json", graphJSON(symbol, "") + " {}"}}); + CHECK(trailing.hasErrors()); + CHECK_EQ(trailing.diagnostics[0].code, std::string("invalid-json")); +} + TEST(LabelMismatchesAreReported) { // Name claims a labeled argument the declaration does not have. std::string symbol = symbolJSON( From 1cf3226bd0f6788b848b95a62acf910f103d8662 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 20 Oct 2026 11:08:35 -0700 Subject: [PATCH 4/5] feat(metadata-generator): Swift capability classifier, coverage and compiler verification PR 2 of the Swift interop plan: decide, per declaration, whether it can be reached from JavaScript, report it, and have the Swift compiler confirm every decision that claims a declaration is callable. - SwiftTypes parses TypeRefs into a type tree (nominal and member types, generics, optionals, collections, tuples, function types with effects and attributes, metatypes, existentials, opaque types, compositions), normalizing Optional/Array/Dictionary and resolving generic parameters in scope. - CapabilityClassifier assigns each symbol one tier (objc-direct, swift-generated, swift-specialized, type-only, unsupported, not-applicable) with stable reason codes, the JS bridge of every parameter and result, JS names, and overload ambiguity. The generated surface bridges primitives, String, optionals, module classes/actors (handles), structs (boxes) and payload-less enums (case names). - CoverageReport writes .coverage.json with per-tier and per-kind counts, a reason histogram, effective (ObjC + Swift) callable counts and every symbol's classification. - ProbeEmitter writes Swift that calls each generated declaration the way a thunk will, through the shared SwiftSource invocation rendering. ProbeVerifier type-checks the probes, maps compiler errors back to symbols, demotes them as compiler-rejected and reclassifies until the probes type-check; symbol graphs cannot express facts like ~Copyable. - New flags: --swift-coverage-output, --swift-probe-output, --swift-verify (with --swift-sdk, --swift-target, --swift-search-path, --swift-framework-search-path, --swift-compiler, --swift-work-dir) and --swift-deployment-target. - Graphs from cross-import overlays record their declaring module so generated code imports and qualifies it correctly. Across SwiftUI, Foundation, Charts, SwiftData, RegexBuilder, WeatherKit and Observation at an iOS 18 deployment target, all generated probes type-check after at most two passes; the compiler rejects two Foundation declarations that use the noncopyable Subprogress. Objective-C output is unchanged. --- metadata-generator/README.md | 55 +- metadata-generator/src/CMakeLists.txt | 14 + .../src/Swift/CapabilityClassifier.cpp | 550 +++++++++ .../src/Swift/CapabilityClassifier.h | 104 ++ .../src/Swift/CoverageReport.cpp | 136 +++ metadata-generator/src/Swift/CoverageReport.h | 21 + .../src/Swift/FragmentTokens.cpp | 109 ++ metadata-generator/src/Swift/FragmentTokens.h | 53 + metadata-generator/src/Swift/ProbeEmitter.cpp | 134 +++ metadata-generator/src/Swift/ProbeEmitter.h | 25 + .../src/Swift/ProbeVerifier.cpp | 126 ++ metadata-generator/src/Swift/ProbeVerifier.h | 48 + metadata-generator/src/Swift/SwiftIR.cpp | 1 + metadata-generator/src/Swift/SwiftIR.h | 3 + metadata-generator/src/Swift/SwiftSource.cpp | 235 ++++ metadata-generator/src/Swift/SwiftSource.h | 76 ++ metadata-generator/src/Swift/SwiftTypes.cpp | 663 +++++++++++ metadata-generator/src/Swift/SwiftTypes.h | 118 ++ .../src/Swift/SymbolGraphLoader.cpp | 139 +-- metadata-generator/src/main.cpp | 139 +++ metadata-generator/tests/CMakeLists.txt | 19 +- .../tests/swift/ClassifierTests.cpp | 335 ++++++ .../tests/swift/SwiftTypesTests.cpp | 215 ++++ .../tests/swift/SymbolGraphLoaderTests.cpp | 117 +- metadata-generator/tests/swift/TestMain.cpp | 5 + metadata-generator/tests/swift/TestSupport.h | 107 ++ .../swift/snapshots/SwiftDemo.coverage.json | 1022 +++++++++++++++++ .../swift/snapshots/SwiftDemo.probe.swift | 254 ++++ 28 files changed, 4594 insertions(+), 229 deletions(-) create mode 100644 metadata-generator/src/Swift/CapabilityClassifier.cpp create mode 100644 metadata-generator/src/Swift/CapabilityClassifier.h create mode 100644 metadata-generator/src/Swift/CoverageReport.cpp create mode 100644 metadata-generator/src/Swift/CoverageReport.h create mode 100644 metadata-generator/src/Swift/FragmentTokens.cpp create mode 100644 metadata-generator/src/Swift/FragmentTokens.h create mode 100644 metadata-generator/src/Swift/ProbeEmitter.cpp create mode 100644 metadata-generator/src/Swift/ProbeEmitter.h create mode 100644 metadata-generator/src/Swift/ProbeVerifier.cpp create mode 100644 metadata-generator/src/Swift/ProbeVerifier.h create mode 100644 metadata-generator/src/Swift/SwiftSource.cpp create mode 100644 metadata-generator/src/Swift/SwiftSource.h create mode 100644 metadata-generator/src/Swift/SwiftTypes.cpp create mode 100644 metadata-generator/src/Swift/SwiftTypes.h create mode 100644 metadata-generator/tests/swift/ClassifierTests.cpp create mode 100644 metadata-generator/tests/swift/SwiftTypesTests.cpp create mode 100644 metadata-generator/tests/swift/TestMain.cpp create mode 100644 metadata-generator/tests/swift/TestSupport.h create mode 100644 metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json create mode 100644 metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift diff --git a/metadata-generator/README.md b/metadata-generator/README.md index 122467be6..b94dbd301 100644 --- a/metadata-generator/README.md +++ b/metadata-generator/README.md @@ -64,6 +64,55 @@ Swift declarations are not callable from JavaScript yet, so the emitted `swift!.d.ts` is type-only: it names the module's top-level types and declares no members. +### Capability classification and coverage + +Every declaration is classified into one tier, with machine-readable reasons +for anything not generated (`src/Swift/CapabilityClassifier.h` lists the +codes): + +| Tier | Meaning | +|---|---| +| `objc-direct` | Objective-C-visible (`c:` USR); served by the existing metadata runtime | +| `swift-generated` | callable through a generated Swift thunk | +| `swift-specialized` | needs an explicit generic specialization first | +| `type-only` | representable in TypeScript, not callable (protocols, type aliases) | +| `unsupported` | not bridgeable yet; `reasons` say why | +| `not-applicable` | not an API surface (deinitializers, macros) | + +The generated surface currently bridges `Bool`, integer and floating-point +types, `String`, optionals of those, module classes and actors (handles), +module structs (boxed copies) and payload-less enums (case-name strings). + +`--swift-coverage-output ` writes `.coverage.json`: counts per +tier and kind, a histogram of reasons, and every symbol's classification. +`effectiveCallable` counts what is callable through either the Objective-C +runtime or a thunk. + +### Compiler verification + +Symbol graphs do not carry every fact a call needs (e.g. `~Copyable` is often +invisible), so the generated surface can be checked by the Swift compiler. +`--swift-probe-output ` writes `.probe.swift`, which calls every +generated declaration the way a thunk will, and a line map back to symbols. +`--swift-verify` type-checks those probes, demotes every declaration the +compiler rejects (`compiler-rejected:`), and repeats until the probes +type-check: + +``` +./objc-metadata-generator --skip-objc \ + --swift-symbolgraph-dir \ + --swift-deployment-target 15.0 \ + --swift-verify \ + --swift-sdk "$(xcrun --sdk iphonesimulator --show-sdk-path)" \ + --swift-target arm64-apple-ios15.0-simulator \ + --swift-search-path \ + --swift-coverage-output +``` + +`--swift-deployment-target` sets the version availability decisions are made +against; it defaults to the minimum version recorded in the graphs, which +`swift-symbolgraph-extract` sets to the SDK version. + ``` ./objc-metadata-generator \ -output-typescript \ @@ -92,7 +141,9 @@ cmake --build build --target swift-symbolgraph-tests ./build/bin/swift-symbolgraph-tests Snapshot # run tests whose name contains "Snapshot" ``` -`IRSnapshot` and `TypeScriptSnapshot` compare against -`tests/swift/snapshots/`. After an intended output change, regenerate them with +The snapshot tests (`IRSnapshot`, `TypeScriptSnapshot`, `CoverageSnapshot`, +`ProbeSnapshot`) compare against `tests/swift/snapshots/`. `ProbesTypeCheck` +and the `Verifier*` tests build the fixture module and run the Swift compiler; +they are skipped when `xcrun` is unavailable. After an intended output change, regenerate them with `NS_UPDATE_SNAPSHOTS=1 ./build/bin/swift-symbolgraph-tests Snapshot` and review the diff. diff --git a/metadata-generator/src/CMakeLists.txt b/metadata-generator/src/CMakeLists.txt index ae2e329df..ef99b399c 100644 --- a/metadata-generator/src/CMakeLists.txt +++ b/metadata-generator/src/CMakeLists.txt @@ -37,6 +37,13 @@ set(GENERATOR_HEADERS Yaml/YamlSerializer.h # Swift support + Swift/CapabilityClassifier.h + Swift/CoverageReport.h + Swift/FragmentTokens.h + Swift/ProbeEmitter.h + Swift/ProbeVerifier.h + Swift/SwiftSource.h + Swift/SwiftTypes.h Swift/SwiftIR.h Swift/SymbolGraphLoader.h TypeScript/SwiftDefinitionWriter.h @@ -70,6 +77,13 @@ set(GENERATOR_SOURCES Utils/memoryStream.cpp # Swift support + Swift/CapabilityClassifier.cpp + Swift/CoverageReport.cpp + Swift/FragmentTokens.cpp + Swift/ProbeEmitter.cpp + Swift/ProbeVerifier.cpp + Swift/SwiftSource.cpp + Swift/SwiftTypes.cpp Swift/SwiftIR.cpp Swift/SymbolGraphLoader.cpp TypeScript/SwiftDefinitionWriter.cpp diff --git a/metadata-generator/src/Swift/CapabilityClassifier.cpp b/metadata-generator/src/Swift/CapabilityClassifier.cpp new file mode 100644 index 000000000..4b8846c88 --- /dev/null +++ b/metadata-generator/src/Swift/CapabilityClassifier.cpp @@ -0,0 +1,550 @@ +#include "CapabilityClassifier.h" + +#include +#include + +#include +#include + +namespace Swift { + +const char* toString(Tier tier) { + switch (tier) { + case Tier::ObjCDirect: + return "objc-direct"; + case Tier::SwiftGenerated: + return "swift-generated"; + case Tier::SwiftSpecialized: + return "swift-specialized"; + case Tier::TypeOnly: + return "type-only"; + case Tier::Unsupported: + return "unsupported"; + case Tier::NotApplicable: + return "not-applicable"; + } + return "unsupported"; +} + +const Capability* Classification::find(const std::string& id) const { + auto it = bySymbol.find(id); + return it == bySymbol.end() ? nullptr : &it->second; +} + +bool isCallableKind(SymbolKind kind) { + switch (kind) { + case SymbolKind::EnumCase: + case SymbolKind::Initializer: + case SymbolKind::InstanceMethod: + case SymbolKind::TypeMethod: + case SymbolKind::Operator: + case SymbolKind::InstanceProperty: + case SymbolKind::TypeProperty: + case SymbolKind::InstanceSubscript: + case SymbolKind::TypeSubscript: + case SymbolKind::Function: + case SymbolKind::Variable: + return true; + default: + return false; + } +} + +namespace { + +std::string availabilityDomain(const Platform& platform) { + llvm::StringRef os = platform.operatingSystem; + if (os == "ios") { + return platform.environment == "macabi" ? "macCatalyst" : "iOS"; + } + if (os == "macosx" || os == "macos") { + return "macOS"; + } + if (os == "tvos") { + return "tvOS"; + } + if (os == "watchos") { + return "watchOS"; + } + if (os == "xros" || os == "visionos") { + return "visionOS"; + } + return os.str(); +} + +bool versionAtMost(const Version& a, const Version& b) { + return std::tie(a.major, a.minor, a.patch) <= + std::tie(b.major, b.minor, b.patch); +} + +bool hasAttribute(const Symbol& symbol, llvm::StringRef attribute) { + for (const auto& candidate : symbol.attributes) { + if (llvm::StringRef(candidate).startswith(attribute)) { + return true; + } + } + return false; +} + +bool isPrimitive(const std::string& usr, Bridge& bridge) { + using namespace KnownTypes; + static const char* integers[] = {kInt, kInt8, kInt16, kInt32, kInt64, + kUInt, kUInt8, kUInt16, kUInt32, kUInt64}; + for (const char* candidate : integers) { + if (usr == candidate) { + bridge = Bridge::Integer; + return true; + } + } + if (usr == kDouble || usr == kFloat || usr == kCGFloat) { + bridge = Bridge::Floating; + return true; + } + if (usr == kBool) { + bridge = Bridge::Bool; + return true; + } + if (usr == kString) { + bridge = Bridge::String; + return true; + } + return false; +} + +class Classifier { + public: + Classifier(const Module& module, + const std::map& rejections) + : _module(module), _rejections(rejections) {} + + Classification run() { + // Types first: member classification depends on the owner's tier. + for (const auto& entry : _module.symbols) { + if (isNominalType(entry.second.kind)) { + _result.bySymbol[entry.first] = classifyType(entry.second); + } + } + for (const auto& entry : _module.symbols) { + if (!isNominalType(entry.second.kind)) { + _result.bySymbol[entry.first] = classifyOther(entry.second); + } + } + resolveNames(); + return std::move(_result); + } + + private: + static Capability make(Tier tier, std::string reason = "") { + Capability capability; + capability.tier = tier; + if (!reason.empty()) { + capability.reasons.push_back(std::move(reason)); + } + return capability; + } + + // Reasons shared by every declaration kind. + bool commonRejection(const Symbol& symbol, Capability& out) const { + auto rejected = _rejections.find(symbol.preciseId); + if (rejected != _rejections.end()) { + out = make(Tier::Unsupported, "compiler-rejected:" + rejected->second); + return true; + } + if (llvm::StringRef(symbol.usr).startswith("c:")) { + out = make(Tier::ObjCDirect, "objc-visible"); + return true; + } + if (symbol.access != AccessLevel::Public && + symbol.access != AccessLevel::Open) { + out = make(Tier::Unsupported, "not-public"); + return true; + } + for (const Availability* availability : + applicableAvailability(_module, symbol)) { + if (availability->isUnconditionallyUnavailable) { + out = make(Tier::Unsupported, "unavailable"); + return true; + } + if (availability->obsoleted && _module.platform.minimumVersion && + versionAtMost(*availability->obsoleted, + *_module.platform.minimumVersion)) { + out = make(Tier::Unsupported, "obsoleted"); + return true; + } + } + return false; + } + + Capability classifyType(const Symbol& symbol) const { + Capability capability; + if (commonRejection(symbol, capability)) { + return capability; + } + if (symbol.kind == SymbolKind::Protocol) { + return make(Tier::TypeOnly, "protocol"); + } + if (!symbol.genericParameters.empty()) { + return make(Tier::SwiftSpecialized, "generic"); + } + if (!symbol.parentId.empty()) { + return make(Tier::Unsupported, "nested-type"); + } + // Graphs show suppressed conformances only when the declaration spells + // them; other noncopyable types are caught by compiler verification. + if (llvm::StringRef(symbol.declarationText).contains("~Copyable")) { + return make(Tier::Unsupported, "noncopyable"); + } + if (llvm::StringRef(symbol.declarationText).contains("~Escapable")) { + return make(Tier::Unsupported, "nonescapable"); + } + if (symbol.kind == SymbolKind::Enum) { + for (const auto& id : symbol.memberIds) { + const Symbol* member = _module.find(id); + if (member && member->kind == SymbolKind::EnumCase && + !member->parameters.empty()) { + return make(Tier::Unsupported, "enum-associated-values"); + } + } + } + return make(Tier::SwiftGenerated); + } + + Capability classifyOther(const Symbol& symbol) const { + Capability capability; + switch (symbol.kind) { + case SymbolKind::Deinitializer: + return make(Tier::NotApplicable, "deinitializer"); + case SymbolKind::Macro: + return make(Tier::NotApplicable, "macro"); + case SymbolKind::Extension: + return make(Tier::NotApplicable, "extension-block"); + case SymbolKind::Unknown: + return make(Tier::Unsupported, "unknown-kind"); + default: + break; + } + if (commonRejection(symbol, capability)) { + return capability; + } + if (symbol.kind == SymbolKind::TypeAlias) { + return make(Tier::TypeOnly, "type-alias"); + } + if (symbol.kind == SymbolKind::AssociatedType) { + return make(Tier::TypeOnly, "associated-type"); + } + + const Symbol* owner = + symbol.parentId.empty() ? nullptr : _module.find(symbol.parentId); + bool isMemberKind = symbol.kind != SymbolKind::Function && + symbol.kind != SymbolKind::Variable; + if (symbol.parentId.empty() && isMemberKind) { + // A member whose owner the graph omits (no memberOf edge). + return make(Tier::Unsupported, "missing-owner"); + } + if (!symbol.parentId.empty()) { + if (!owner) { + return make(Tier::Unsupported, "external-type-extension"); + } + if (owner->kind == SymbolKind::Protocol) { + return make(Tier::TypeOnly, "protocol-requirement"); + } + const Capability* ownerCapability = _result.find(owner->preciseId); + if (!ownerCapability || ownerCapability->tier != Tier::SwiftGenerated) { + Tier tier = + ownerCapability && ownerCapability->tier == Tier::SwiftSpecialized + ? Tier::SwiftSpecialized + : Tier::Unsupported; + return make(tier, "owner-not-bridged"); + } + } + + if (symbol.kind == SymbolKind::Operator) { + return make(Tier::Unsupported, "operator"); + } + if (symbol.kind == SymbolKind::InstanceSubscript || + symbol.kind == SymbolKind::TypeSubscript) { + return make(Tier::Unsupported, "subscript"); + } + if (symbol.kind == SymbolKind::EnumCase) { + // Only payload-less enums are bridged (see classifyType). + capability = make(Tier::SwiftGenerated); + capability.jsName = symbol.baseName; + return capability; + } + + if (!symbol.genericParameters.empty()) { + return make(Tier::SwiftSpecialized, "generic"); + } + + bool nonisolated = hasAttribute(symbol, "nonisolated"); + if (!nonisolated && (hasAttribute(symbol, "@MainActor") || + (owner && hasAttribute(*owner, "@MainActor")))) { + return make(Tier::Unsupported, "main-actor"); + } + if (owner && owner->kind == SymbolKind::Actor && !nonisolated && + !symbol.isStatic && symbol.kind != SymbolKind::Initializer) { + return make(Tier::Unsupported, "actor-isolated"); + } + if (symbol.isAsync) { + return make(Tier::Unsupported, "async"); + } + + std::set generics = genericNamesInScope(_module, symbol); + std::vector reasons; + for (const auto& parameter : symbol.parameters) { + if (parameter.modifier == "inout") { + reasons.push_back("inout-parameter"); + continue; + } + if (parameter.isVariadic) { + reasons.push_back("variadic-parameter"); + continue; + } + if (std::find(parameter.attributes.begin(), parameter.attributes.end(), + "@autoclosure") != parameter.attributes.end()) { + reasons.push_back("closure"); + continue; + } + BridgedType bridged = bridge(parameter.type, generics, reasons); + capability.parameters.push_back(std::move(bridged)); + } + + if (symbol.kind == SymbolKind::Initializer) { + // Initializers produce the owner; failable ones may produce nil. + BridgedType self = bridgeOwner(*owner); + self.optional = symbol.isFailable; + capability.result = std::move(self); + } else if (symbol.valueType) { + capability.result = bridge(*symbol.valueType, generics, reasons); + } else if (symbol.returnType) { + capability.result = bridge(*symbol.returnType, generics, reasons); + } else { + capability.result.bridge = Bridge::Void; + } + + std::sort(reasons.begin(), reasons.end()); + reasons.erase(std::unique(reasons.begin(), reasons.end()), reasons.end()); + if (!reasons.empty()) { + bool onlyGeneric = + std::all_of(reasons.begin(), reasons.end(), + [](const std::string& r) { return r == "generic"; }); + return Capability{ + onlyGeneric ? Tier::SwiftSpecialized : Tier::Unsupported, + reasons, + "", + false, + {}, + {}}; + } + + capability.tier = Tier::SwiftGenerated; + capability.jsName = symbol.kind == SymbolKind::Initializer + ? "constructor" + : symbol.baseName; + return capability; + } + + BridgedType bridgeOwner(const Symbol& owner) const { + BridgedType bridged; + bridged.symbolId = owner.preciseId; + bridged.bridge = owner.kind == SymbolKind::Struct ? Bridge::StructBox + : owner.kind == SymbolKind::Enum ? Bridge::EnumCase + : Bridge::ClassHandle; + TypeNode::Component component; + component.name = owner.name; + component.usr = owner.preciseId; + bridged.node.kind = TypeNode::Kind::Nominal; + bridged.node.components.push_back(std::move(component)); + return bridged; + } + + BridgedType bridge(const TypeRef& type, const std::set& generics, + std::vector& reasons) const { + bool complete = true; + BridgedType bridged; + bridged.node = parseType(type, generics, &complete); + if (!complete) { + reasons.push_back("unparsed-type"); + return bridged; + } + const TypeNode* node = &bridged.node; + if (node->kind == TypeNode::Kind::Optional || + node->kind == TypeNode::Kind::ImplicitlyUnwrappedOptional) { + bridged.optional = true; + node = &node->children[0]; + if (node->kind == TypeNode::Kind::Optional || + node->kind == TypeNode::Kind::ImplicitlyUnwrappedOptional) { + reasons.push_back("nested-optional"); + return bridged; + } + } + std::string reason = bridgeNonOptional(*node, bridged); + if (!reason.empty()) { + reasons.push_back(reason); + } + return bridged; + } + + // Returns the rejection reason, or "" with `bridged` filled in. + std::string bridgeNonOptional(const TypeNode& node, + BridgedType& bridged) const { + switch (node.kind) { + case TypeNode::Kind::Void: + bridged.bridge = Bridge::Void; + return ""; + case TypeNode::Kind::GenericParameter: + return "generic"; + case TypeNode::Kind::Function: + return "closure"; + case TypeNode::Kind::Tuple: + return "tuple"; + case TypeNode::Kind::Array: + case TypeNode::Kind::Dictionary: + return "collection"; + case TypeNode::Kind::Existential: + case TypeNode::Kind::Composition: + return "existential"; + case TypeNode::Kind::Opaque: + return "opaque-type"; + case TypeNode::Kind::Metatype: + return "metatype"; + case TypeNode::Kind::Unknown: + return "unparsed-type"; + case TypeNode::Kind::Optional: + case TypeNode::Kind::ImplicitlyUnwrappedOptional: + return "nested-optional"; + case TypeNode::Kind::Nominal: + break; + } + + const std::string& usr = node.usr(); + if (node.components.size() == 1 && node.components[0].arguments.empty() && + isPrimitive(usr, bridged.bridge)) { + return ""; + } + const Symbol* target = usr.empty() ? nullptr : _module.find(usr); + if (target) { + const Capability* capability = _result.find(target->preciseId); + if (capability && capability->tier == Tier::SwiftGenerated && + target->kind != SymbolKind::Protocol) { + bridged = BridgedType{bridgeOwner(*target).bridge, bridged.optional, + target->preciseId, bridged.node}; + return ""; + } + return "unbridged-type:" + llvm::join(target->pathComponents, "."); + } + auto name = _module.externalNames.find(usr); + if (name != _module.externalNames.end()) { + return "unbridged-type:" + name->second; + } + std::string qualified = qualifiedNameFromUSR(usr); + return "unbridged-type:" + (qualified.empty() ? spelling(node) : qualified); + } + + // JS names for SwiftGenerated members and overload ambiguity. + void resolveNames() { + struct Entry { + std::string id; + bool isProperty; + std::string signature; + }; + std::map, std::vector> + groups; + for (auto& entry : _result.bySymbol) { + Capability& capability = entry.second; + if (capability.tier != Tier::SwiftGenerated || + capability.jsName.empty()) { + continue; + } + const Symbol* symbol = _module.find(entry.first); + bool isProperty = symbol->kind == SymbolKind::InstanceProperty || + symbol->kind == SymbolKind::TypeProperty || + symbol->kind == SymbolKind::Variable || + symbol->kind == SymbolKind::EnumCase; + bool isStatic = symbol->isStatic || + symbol->kind == SymbolKind::EnumCase || + symbol->kind == SymbolKind::Initializer; + std::string signature = std::to_string(capability.parameters.size()); + for (const auto& parameter : capability.parameters) { + signature += "," + jsKind(parameter); + } + groups[{symbol->parentId, capability.jsName, isStatic}].push_back( + Entry{entry.first, isProperty, signature}); + } + + for (auto& group : groups) { + auto& entries = group.second; + bool hasProperty = + std::any_of(entries.begin(), entries.end(), + [](const Entry& e) { return e.isProperty; }); + for (const auto& entry : entries) { + Capability& capability = _result.bySymbol[entry.id]; + if (hasProperty && entries.size() > 1) { + // A JS property and method cannot share a key; the property wins. + if (!entry.isProperty) { + capability.tier = Tier::Unsupported; + capability.reasons = {"js-name-conflict"}; + capability.jsName.clear(); + capability.parameters.clear(); + } + continue; + } + for (const auto& other : entries) { + if (&other != &entry && other.signature == entry.signature) { + capability.ambiguousOverload = true; + } + } + } + } + } + + static std::string jsKind(const BridgedType& type) { + std::string kind; + switch (type.bridge) { + case Bridge::Bool: + kind = "boolean"; + break; + case Bridge::Integer: + case Bridge::Floating: + kind = "number"; + break; + case Bridge::String: + case Bridge::EnumCase: + kind = "string"; + break; + case Bridge::ClassHandle: + case Bridge::StructBox: + kind = "object:" + type.symbolId; + break; + default: + kind = "other"; + break; + } + return type.optional ? kind + "?" : kind; + } + + const Module& _module; + const std::map& _rejections; + Classification _result; +}; + +} // namespace + +std::vector applicableAvailability(const Module& module, + const Symbol& symbol) { + std::string domain = availabilityDomain(module.platform); + std::vector result; + for (const auto& availability : symbol.availability) { + if (availability.domain == "*" || availability.domain == domain) { + result.push_back(&availability); + } + } + return result; +} + +Classification classify(const Module& module, + const std::map& rejections) { + return Classifier(module, rejections).run(); +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/CapabilityClassifier.h b/metadata-generator/src/Swift/CapabilityClassifier.h new file mode 100644 index 000000000..db0bf8fdd --- /dev/null +++ b/metadata-generator/src/Swift/CapabilityClassifier.h @@ -0,0 +1,104 @@ +#pragma once + +#include +#include +#include + +#include "SwiftIR.h" +#include "SwiftTypes.h" + +namespace Swift { + +// How a declaration is (or is not) reachable from JavaScript. +enum class Tier { + // Objective-C-visible (`c:` USR): served by the existing metadata runtime. + ObjCDirect, + // Callable through a generated Swift thunk. + SwiftGenerated, + // Needs an explicit generic specialization or adapter before it can be + // generated. + SwiftSpecialized, + // Representable in TypeScript but not callable (protocols, type aliases, + // protocol requirements). + TypeOnly, + Unsupported, + // Not an API surface (deinitializers, macros, extension blocks). + NotApplicable, +}; + +const char* toString(Tier tier); + +// How a Swift type crosses into JavaScript. Only types with a bridge other +// than None can appear in generated signatures. +enum class Bridge { + None, + Void, + Bool, + // Integers: JS numbers; values outside +/-(2^53 - 1) throw RangeError + // instead of losing precision. + Integer, + Floating, + String, + // Module class or actor: an owned handle with stable JS identity. + ClassHandle, + // Module struct: a boxed copy; the JS object never aliases another copy. + StructBox, + // Module enum without payloads: its case name as a JS string. + EnumCase, +}; + +struct BridgedType { + Bridge bridge = Bridge::None; + bool optional = false; + // Nominal bridges: the module symbol the type refers to. + std::string symbolId; + TypeNode node; +}; + +struct Capability { + Tier tier = Tier::NotApplicable; + // Stable machine-readable codes, optionally with a detail after ':' + // ("unbridged-type:Foundation.URL"). Codes: + // objc-visible, not-public, unavailable, obsoleted, unknown-kind, + // deinitializer, macro, extension-block, protocol, protocol-requirement, + // type-alias, associated-type, generic, nested-type, noncopyable, + // nonescapable, actor-isolated, + // main-actor, async, operator, subscript, enum-associated-values, + // external-type-extension, owner-not-bridged, missing-owner, + // js-name-conflict, + // inout-parameter, variadic-parameter, closure, tuple, collection, + // existential, opaque-type, metatype, unbridged-type, unparsed-type, + // nested-optional, compiler-rejected + std::vector reasons; + // Property name, method name, or "constructor" for initializers. + std::string jsName; + // Another generated overload with the same JS name accepts the same JS + // argument kinds, so JS-side dispatch must use the signature key. + bool ambiguousOverload = false; + + // Bridges for SwiftGenerated callables: parameters in order, then the + // result (or the property value type). + std::vector parameters; + BridgedType result; +}; + +struct Classification { + std::map bySymbol; + + const Capability* find(const std::string& id) const; +}; + +// `rejections` maps symbol ids the compiler refused (see ProbeVerifier) to +// the compiler's message; those symbols are classified compiler-rejected. +Classification classify( + const Module& module, + const std::map& rejections = {}); + +// Whether `kind` is something JavaScript can call or read. +bool isCallableKind(SymbolKind kind); + +// The availability entries that apply to `module`'s platform. +std::vector applicableAvailability(const Module& module, + const Symbol& symbol); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/CoverageReport.cpp b/metadata-generator/src/Swift/CoverageReport.cpp new file mode 100644 index 000000000..470dbb067 --- /dev/null +++ b/metadata-generator/src/Swift/CoverageReport.cpp @@ -0,0 +1,136 @@ +#include "CoverageReport.h" + +#include +#include +#include + +#include + +namespace Swift { + +namespace { + +const Tier kTiers[] = {Tier::ObjCDirect, Tier::SwiftGenerated, + Tier::SwiftSpecialized, Tier::TypeOnly, + Tier::Unsupported, Tier::NotApplicable}; + +struct Counts { + std::map byTier; + int total = 0; + + void add(Tier tier) { + byTier[tier]++; + total++; + } +}; + +void writeCounts(llvm::json::OStream& out, const Counts& counts) { + out.attribute("total", counts.total); + for (Tier tier : kTiers) { + auto it = counts.byTier.find(tier); + out.attribute(toString(tier), it == counts.byTier.end() ? 0 : it->second); + } +} + +} // namespace + +std::string coverageJSON(const Module& module, + const Classification& classification, + int compilerRuns) { + Counts declarations; + Counts callable; + std::map byKind; + std::map reasons; + + for (const auto& entry : module.symbols) { + const Symbol& symbol = entry.second; + const Capability* capability = classification.find(entry.first); + if (!capability) { + continue; + } + declarations.add(capability->tier); + byKind[toString(symbol.kind)].add(capability->tier); + if (isCallableKind(symbol.kind)) { + callable.add(capability->tier); + } + if (capability->tier == Tier::Unsupported || + capability->tier == Tier::SwiftSpecialized) { + for (const auto& reason : capability->reasons) { + reasons[llvm::StringRef(reason).split(':').first.str()]++; + } + } + } + + std::string result; + llvm::raw_string_ostream stream(result); + llvm::json::OStream out(stream, 2); + out.object([&] { + out.attribute("module", module.name); + out.attributeObject("totals", [&] { + out.attributeObject("declarations", + [&] { writeCounts(out, declarations); }); + out.attributeObject("callable", [&] { writeCounts(out, callable); }); + // Callable through any path: the Objective-C runtime or a thunk. + out.attribute("effectiveCallable", + callable.byTier[Tier::ObjCDirect] + + callable.byTier[Tier::SwiftGenerated]); + if (compilerRuns < 0) { + out.attribute("compilerVerified", false); + } else { + out.attribute("compilerVerified", true); + out.attribute("compilerRuns", compilerRuns); + } + out.attribute("compiledThunks", nullptr); + out.attribute("runtimeTested", nullptr); + }); + out.attributeObject("byKind", [&] { + for (const auto& entry : byKind) { + out.attributeObject(entry.first, + [&] { writeCounts(out, entry.second); }); + } + }); + out.attributeObject("reasons", [&] { + for (const auto& entry : reasons) { + out.attribute(entry.first, entry.second); + } + }); + out.attributeArray("symbols", [&] { + for (const auto& entry : module.symbols) { + const Symbol& symbol = entry.second; + const Capability* capability = classification.find(entry.first); + if (!capability) { + continue; + } + out.object([&] { + out.attribute("id", symbol.preciseId); + out.attribute("path", llvm::join(symbol.pathComponents, ".")); + out.attribute("kind", toString(symbol.kind)); + out.attribute("tier", toString(capability->tier)); + if (!capability->reasons.empty()) { + out.attributeArray("reasons", [&] { + for (const auto& reason : capability->reasons) { + out.value(reason); + } + }); + } + if (!capability->jsName.empty()) { + out.attribute("jsName", capability->jsName); + } + if (capability->ambiguousOverload) { + out.attribute("ambiguousOverload", true); + } + if (symbol.location) { + out.attribute("location", + symbol.location->uri + ":" + + std::to_string(symbol.location->line + 1)); + } + }); + } + }); + }); + stream << "\n"; + stream.flush(); + return result; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/CoverageReport.h b/metadata-generator/src/Swift/CoverageReport.h new file mode 100644 index 000000000..39860ff6a --- /dev/null +++ b/metadata-generator/src/Swift/CoverageReport.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "CapabilityClassifier.h" +#include "SwiftIR.h" + +namespace Swift { + +// `.coverage.json`: per-tier and per-kind counts, unsupported reason +// histogram, and the classification of every symbol. `compiledThunks` and +// `runtimeTested` stay null until a later stage measures them. +// +// `compilerRuns` is the number of type-check passes behind `classification` +// (see ProbeVerifier), or -1 when the classification was not compiler +// verified. +std::string coverageJSON(const Module& module, + const Classification& classification, + int compilerRuns = -1); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/FragmentTokens.cpp b/metadata-generator/src/Swift/FragmentTokens.cpp new file mode 100644 index 000000000..7c573096c --- /dev/null +++ b/metadata-generator/src/Swift/FragmentTokens.cpp @@ -0,0 +1,109 @@ +#include "FragmentTokens.h" + +#include + +namespace Swift { +namespace FragmentTokens { + +Tokens tokenize(const Fragments& fragments) { + Tokens tokens; + for (const auto& fragment : fragments) { + // Custom attributes (global actors, property wrappers) arrive as an "@" + // fragment followed by the attribute type's name, which inside types is a + // typeIdentifier (`@MainActor (Message) -> Void`). + if ((fragment.kind == "attribute" || fragment.kind == "typeIdentifier") && + !tokens.empty() && tokens.back().isFragment("attribute") && + tokens.back().text == "@") { + tokens.back().text += fragment.spelling; + tokens.back().precise = fragment.preciseIdentifier; + continue; + } + if (fragment.kind != "text") { + tokens.push_back(Token{Token::Type::Fragment, fragment.kind, + fragment.spelling, fragment.preciseIdentifier}); + continue; + } + + llvm::StringRef text = fragment.spelling; + // Some attributes arrive as plain text ("@backDeployed(before: iOS + // 17.0)\n", "@abi(func f(...))"). Only the name becomes the attribute + // token; its argument list is tokenized normally so consumeAttribute can + // match the parentheses, which may close in a later fragment. + if (text.ltrim().startswith("@")) { + llvm::StringRef rest = text.ltrim(); + size_t nameEnd = 1; + while (nameEnd < rest.size() && + (llvm::isAlnum(rest[nameEnd]) || rest[nameEnd] == '_')) { + nameEnd++; + } + tokens.push_back(Token{Token::Type::Fragment, "attribute", + rest.take_front(nameEnd).str(), ""}); + text = rest.drop_front(nameEnd); + } + + size_t i = 0; + while (i < text.size()) { + char c = text[i]; + if (llvm::isSpace(c)) { + size_t end = i; + while (end < text.size() && llvm::isSpace(text[end])) { + end++; + } + tokens.push_back( + Token{Token::Type::Space, "text", text.slice(i, end).str(), ""}); + i = end; + } else if (text.substr(i).startswith("->")) { + tokens.push_back(Token{Token::Type::Arrow, "text", "->", ""}); + i += 2; + } else if (llvm::StringRef("()[]<>,:?!={}&").contains(c)) { + tokens.push_back( + Token{Token::Type::Punct, "text", std::string(1, c), ""}); + i++; + } else { + size_t end = i; + while (end < text.size() && !llvm::isSpace(text[end]) && + !llvm::StringRef("()[]<>,:?!={}&").contains(text[end]) && + !text.substr(end).startswith("->")) { + end++; + } + llvm::StringRef word = text.slice(i, end); + // "@" inside text starts an attribute whose name may follow as its + // own fragment (": @" + typeIdentifier "MainActor"). + if (word.startswith("@")) { + tokens.push_back( + Token{Token::Type::Fragment, "attribute", word.str(), ""}); + } else { + tokens.push_back(Token{Token::Type::Word, "text", word.str(), ""}); + } + i = end; + } + } + } + return tokens; +} + +TypeRef makeTypeRef(Tokens::const_iterator begin, Tokens::const_iterator end) { + while (begin != end && begin->type == Token::Type::Space) { + ++begin; + } + while (end != begin && std::prev(end)->type == Token::Type::Space) { + --end; + } + + TypeRef type; + for (auto it = begin; it != end; ++it) { + type.spelling += it->text; + if (it->type == Token::Type::Fragment) { + type.fragments.push_back(Fragment{it->kind, it->text, it->precise}); + } else if (!type.fragments.empty() && + type.fragments.back().kind == "text") { + type.fragments.back().spelling += it->text; + } else { + type.fragments.push_back(Fragment{"text", it->text, ""}); + } + } + return type; +} + +} // namespace FragmentTokens +} // namespace Swift diff --git a/metadata-generator/src/Swift/FragmentTokens.h b/metadata-generator/src/Swift/FragmentTokens.h new file mode 100644 index 000000000..d58c8eda4 --- /dev/null +++ b/metadata-generator/src/Swift/FragmentTokens.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +#include +#include + +#include "SwiftIR.h" + +// Symbol graphs carry most semantics (effects, settability, labels, failable +// initializers, actor-ness) only inside `declarationFragments`, where +// structural punctuation is mixed into "text" fragments (e.g. "?) -> "). +// Text fragments are therefore split into single structural tokens before +// parsing. +namespace Swift { +namespace FragmentTokens { + +struct Token { + enum class Type { Fragment, Punct, Space, Word, Arrow }; + Type type; + // Fragment kind for Fragment tokens, "text" otherwise. + std::string kind; + std::string text; + std::string precise; + + bool isPunct(char c) const { + return type == Type::Punct && text.size() == 1 && text[0] == c; + } + bool isFragment(llvm::StringRef fragmentKind) const { + return type == Type::Fragment && kind == fragmentKind; + } + bool isKeyword(llvm::StringRef keyword) const { + return isFragment("keyword") && text == keyword; + } +}; + +using Tokens = std::vector; + +Tokens tokenize(const Fragments& fragments); + +inline bool opens(const Token& token) { + return token.isPunct('(') || token.isPunct('[') || token.isPunct('<'); +} + +inline bool closes(const Token& token) { + return token.isPunct(')') || token.isPunct(']') || token.isPunct('>'); +} + +// The tokens in [begin, end) as a TypeRef, without surrounding whitespace. +TypeRef makeTypeRef(Tokens::const_iterator begin, Tokens::const_iterator end); + +} // namespace FragmentTokens +} // namespace Swift diff --git a/metadata-generator/src/Swift/ProbeEmitter.cpp b/metadata-generator/src/Swift/ProbeEmitter.cpp new file mode 100644 index 000000000..b4c7d668a --- /dev/null +++ b/metadata-generator/src/Swift/ProbeEmitter.cpp @@ -0,0 +1,134 @@ +#include "ProbeEmitter.h" + +#include + +#include "SwiftSource.h" + +namespace Swift { + +namespace { + +// Every line written between begin() and end() maps to that symbol: the +// compiler reports some errors on the declaration line (parameter types), +// others on the statement. +class Writer { + public: + void begin(const std::string& symbolId) { _symbolId = symbolId; } + void end() { _symbolId.clear(); } + + void line(const std::string& text) { + _source += text + "\n"; + _line++; + if (!_symbolId.empty()) { + _map[_line] = _symbolId; + } + } + + ProbeSource finish() { + return ProbeSource{std::move(_source), std::move(_map)}; + } + + private: + std::string _source; + std::map _map; + std::string _symbolId; + int _line = 0; +}; + +} // namespace + +ProbeSource emitProbes(const Module& module, + const Classification& classification) { + Writer out; + out.line( + "// Generated by objc-metadata-generator. Compiler-validation probes " + "for"); + out.line("// the Swift-generated surface of module " + module.name + "."); + out.line("import Foundation"); + out.line("import " + module.name); + std::set overlays; + for (const auto& entry : module.symbols) { + const Capability* capability = classification.find(entry.first); + if (capability && capability->tier == Tier::SwiftGenerated && + !entry.second.declaringModule.empty()) { + overlays.insert(entry.second.declaringModule); + } + } + for (const auto& overlay : overlays) { + out.line("import " + overlay); + } + out.line(""); + + int index = 0; + for (const auto& entry : module.symbols) { + const Symbol& symbol = entry.second; + const Capability* capability = classification.find(entry.first); + if (!capability || capability->tier != Tier::SwiftGenerated) { + continue; + } + + if (isNominalType(symbol.kind)) { + // Bridged types are copied in and out of boxes and handles, which + // requires Copyable (not visible in symbol graphs). + std::string type = qualifiedTypeName(module, symbol); + std::string availability = availabilityCondition(module, symbol); + out.begin(symbol.preciseId); + out.line("// " + symbol.preciseId); + if (!availability.empty()) { + out.line("@available(" + availability + ")"); + } + out.line("func __nsProbe" + std::to_string(index++) + + "(_ value: " + type + ") -> " + type + " { value }"); + out.end(); + out.line(""); + continue; + } + if (!isCallableKind(symbol.kind)) { + continue; + } + + Invocation invocation = describeInvocation(module, symbol, *capability); + std::vector parameters; + if (invocation.needsReceiver) { + parameters.push_back( + "_ receiver: " + + std::string(invocation.receiverIsInout ? "inout " : "") + + invocation.owner); + } + std::vector arguments; + for (size_t i = 0; i < invocation.parameterTypes.size(); i++) { + std::string name = "a" + std::to_string(i); + parameters.push_back("_ " + name + ": " + invocation.parameterTypes[i]); + arguments.push_back(name); + } + if (invocation.isSettable) { + parameters.push_back("_ newValue: " + invocation.resultType); + } + std::string signature; + for (size_t i = 0; i < parameters.size(); i++) { + signature += (i > 0 ? ", " : "") + parameters[i]; + } + + out.begin(symbol.preciseId); + out.line("// " + symbol.preciseId); + // The receiver and parameter types may themselves be gated, so the whole + // probe carries the availability rather than an #available check. + if (!invocation.availability.empty()) { + out.line("@available(" + invocation.availability + ")"); + } + out.line("func __nsProbe" + std::to_string(index++) + "(" + signature + + ")" + (invocation.isThrowing ? " throws" : "") + " {"); + const std::string receiver = "receiver"; + out.line(" let _: " + invocation.resultType + " = " + + invocationExpression(invocation, receiver, arguments)); + if (invocation.isSettable) { + out.line(" " + assignmentStatement(invocation, receiver, "newValue")); + } + out.line("}"); + out.end(); + out.line(""); + } + return out.finish(); +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/ProbeEmitter.h b/metadata-generator/src/Swift/ProbeEmitter.h new file mode 100644 index 000000000..28691d301 --- /dev/null +++ b/metadata-generator/src/Swift/ProbeEmitter.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "CapabilityClassifier.h" +#include "SwiftIR.h" + +namespace Swift { + +// Swift source that exercises every SwiftGenerated symbol the way a thunk +// will (`let _: Result = try owner.member(label: argument)`). Type-checking it +// against the module proves the IR's labels, types, optionality and effects +// match what the compiler accepts. +struct ProbeSource { + std::string source; + // 1-based source line -> symbol id, for mapping compiler diagnostics back + // to the symbol they reject. + std::map lineToSymbol; +}; + +ProbeSource emitProbes(const Module& module, + const Classification& classification); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/ProbeVerifier.cpp b/metadata-generator/src/Swift/ProbeVerifier.cpp new file mode 100644 index 000000000..337c84521 --- /dev/null +++ b/metadata-generator/src/Swift/ProbeVerifier.cpp @@ -0,0 +1,126 @@ +#include "ProbeVerifier.h" + +#include +#include +#include +#include +#include +#include + +#include "ProbeEmitter.h" + +namespace Swift { + +std::map rejectionsFromLog( + const std::string& log, const std::string& probePath, + const std::map& lineToSymbol, + std::vector& unmapped) { + std::map rejections; + llvm::SmallVector lines; + llvm::StringRef(log).split(lines, '\n'); + for (llvm::StringRef line : lines) { + if (!line.consume_front(probePath) || !line.consume_front(":")) { + continue; + } + auto lineNumber = line.split(':'); + auto column = lineNumber.second.split(':'); + llvm::StringRef message = column.second.trim(); + int number = 0; + if (lineNumber.first.getAsInteger(10, number) || + !message.consume_front("error:")) { + continue; + } + message = message.trim(); + auto symbol = lineToSymbol.find(number); + if (symbol == lineToSymbol.end()) { + unmapped.push_back(std::to_string(number) + ": " + message.str()); + continue; + } + rejections.emplace(symbol->second, message.str()); + } + return rejections; +} + +VerifyResult verifyWithCompiler(const Module& module, + const VerifyOptions& options) { + VerifyResult result; + if (options.compiler.empty()) { + result.failure = "no compiler configured"; + return result; + } + auto program = llvm::sys::findProgramByName(options.compiler[0]); + if (!program) { + result.failure = "compiler '" + options.compiler[0] + "' not found"; + return result; + } + + llvm::SmallString<256> probePath(options.workDirectory); + llvm::sys::path::append(probePath, module.name + ".verify.swift"); + llvm::SmallString<256> logPath(options.workDirectory); + llvm::sys::path::append(logPath, module.name + ".verify.log"); + llvm::sys::fs::create_directories(options.workDirectory); + + // Each pass demotes at least one symbol, so the loop terminates; the bound + // only guards against a compiler that keeps reporting the same errors. + for (int pass = 0; pass < 8; pass++) { + result.classification = classify(module, result.rejections); + ProbeSource probes = emitProbes(module, result.classification); + { + std::error_code error; + llvm::raw_fd_ostream out(probePath, error, llvm::sys::fs::OF_Text); + if (error) { + result.failure = probePath.str().str() + ": " + error.message(); + return result; + } + out << probes.source; + } + + std::vector arguments(options.compiler.begin(), + options.compiler.end()); + arguments.insert(arguments.end(), {"-typecheck", "-sdk", options.sdk, + "-target", options.target}); + for (const auto& path : options.searchPaths) { + arguments.insert(arguments.end(), {"-I", path}); + } + for (const auto& path : options.frameworkSearchPaths) { + arguments.insert(arguments.end(), {"-F", path}); + } + arguments.push_back(probePath.str().str()); + std::vector argv(arguments.begin(), arguments.end()); + std::optional redirects[] = { + std::nullopt, llvm::StringRef(logPath), llvm::StringRef(logPath)}; + std::string executionError; + int status = llvm::sys::ExecuteAndWait(*program, argv, std::nullopt, + redirects, 0, 0, &executionError); + result.compilerRuns++; + if (status < 0) { + result.failure = "compiler did not run: " + executionError; + return result; + } + if (status == 0) { + return result; + } + + auto log = llvm::MemoryBuffer::getFile(logPath); + std::vector unmapped; + auto rejections = + rejectionsFromLog(log ? (*log)->getBuffer().str() : "", + probePath.str().str(), probes.lineToSymbol, unmapped); + if (!unmapped.empty()) { + result.failure = "compiler errors outside any probe (see " + + logPath.str().str() + "): " + unmapped.front(); + return result; + } + size_t before = result.rejections.size(); + result.rejections.insert(rejections.begin(), rejections.end()); + if (result.rejections.size() == before) { + result.failure = "compiler failed without reporting probe errors (see " + + logPath.str().str() + ")"; + return result; + } + } + result.failure = "probes still fail to type-check after repeated demotion"; + return result; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/ProbeVerifier.h b/metadata-generator/src/Swift/ProbeVerifier.h new file mode 100644 index 000000000..459764aa2 --- /dev/null +++ b/metadata-generator/src/Swift/ProbeVerifier.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +#include "CapabilityClassifier.h" +#include "SwiftIR.h" + +namespace Swift { + +struct VerifyOptions { + // Compiler driver and leading arguments, e.g. {"xcrun", "swiftc"}. + std::vector compiler = {"xcrun", "swiftc"}; + std::string sdk; + std::string target; + // Directories holding the modules' .swiftmodule / frameworks. + std::vector searchPaths; + std::vector frameworkSearchPaths; + // Scratch directory for probe sources and compiler logs. + std::string workDirectory; +}; + +struct VerifyResult { + Classification classification; + // Symbol id -> first compiler error reported against its probe. + std::map rejections; + int compilerRuns = 0; + // Set when verification could not complete: the compiler failed to run, or + // reported errors that map to no probe (e.g. the module cannot be + // imported). + std::string failure; +}; + +// Classifies `module`, type-checks probes for the result, demotes every +// symbol whose probe the compiler rejects, and repeats until the probes +// type-check (demoting a type changes its members' classification). +VerifyResult verifyWithCompiler(const Module& module, + const VerifyOptions& options); + +// "probe.swift:12:7: error: message" lines of `log` for `probePath`, mapped +// through `lineToSymbol`. Errors on unmapped lines go to `unmapped`. +std::map rejectionsFromLog( + const std::string& log, const std::string& probePath, + const std::map& lineToSymbol, + std::vector& unmapped); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SwiftIR.cpp b/metadata-generator/src/Swift/SwiftIR.cpp index 92efeb593..71361a7c8 100644 --- a/metadata-generator/src/Swift/SwiftIR.cpp +++ b/metadata-generator/src/Swift/SwiftIR.cpp @@ -274,6 +274,7 @@ void writeSymbol(OStream& out, const Symbol& symbol) { std::to_string(symbol.location->character)); } out.attribute("graph", symbol.sourceGraph); + writeNonEmpty(out, "declaringModule", symbol.declaringModule); writeNonEmpty(out, "parent", symbol.parentId); writeStringArray(out, "members", symbol.memberIds); diff --git a/metadata-generator/src/Swift/SwiftIR.h b/metadata-generator/src/Swift/SwiftIR.h index 4ebc68641..382955c07 100644 --- a/metadata-generator/src/Swift/SwiftIR.h +++ b/metadata-generator/src/Swift/SwiftIR.h @@ -193,6 +193,9 @@ struct Symbol { std::optional location; // Graph file the symbol was read from, relative to the scanned directory. std::string sourceGraph; + // Set when a cross-import overlay (`_SwiftData_SwiftUI`) rather than the + // module itself declares the symbol; code using it must import the overlay. + std::string declaringModule; // Resolved relationships. std::string parentId; diff --git a/metadata-generator/src/Swift/SwiftSource.cpp b/metadata-generator/src/Swift/SwiftSource.cpp new file mode 100644 index 000000000..828b90d1c --- /dev/null +++ b/metadata-generator/src/Swift/SwiftSource.cpp @@ -0,0 +1,235 @@ +#include "SwiftSource.h" + +#include + +#include + +namespace Swift { + +std::string declaringModuleName(const Module& module, const Symbol& symbol) { + return symbol.declaringModule.empty() ? module.name : symbol.declaringModule; +} + +std::string qualifiedTypeName(const Module& module, const Symbol& symbol) { + return declaringModuleName(module, symbol) + "." + + llvm::join(symbol.pathComponents, "."); +} + +namespace { + +TypeNode qualify(const TypeNode& node, const Module& module) { + TypeNode result = node; + for (auto& child : result.children) { + child = qualify(child, module); + } + for (auto& child : result.result) { + child = qualify(child, module); + } + for (auto& child : result.thrownType) { + child = qualify(child, module); + } + for (auto& component : result.components) { + for (auto& argument : component.arguments) { + argument = qualify(argument, module); + } + } + if (result.kind == TypeNode::Kind::Nominal) { + const Symbol* symbol = module.find(result.usr()); + if (symbol && isNominalType(symbol->kind)) { + std::vector components; + components.push_back( + TypeNode::Component{declaringModuleName(module, *symbol), "", {}}); + for (const auto& name : symbol->pathComponents) { + components.push_back(TypeNode::Component{name, "", {}}); + } + components.back().usr = symbol->preciseId; + components.back().arguments = result.components.back().arguments; + result.components = std::move(components); + } + } + return result; +} + +std::string ownerTypeText(const Module& module, const Symbol& owner) { + return qualifiedTypeName(module, owner); +} + +std::string typeText(const BridgedType& bridged, const Module& module) { + if (bridged.bridge == Bridge::Void) { + return "Void"; + } + return swiftTypeText(bridged.node, module); +} + +bool isAfter(const Version& a, const Version& b) { + return std::tie(a.major, a.minor, a.patch) > + std::tie(b.major, b.minor, b.patch); +} + +std::string platformName(const Module& module) { + const std::string& os = module.platform.operatingSystem; + if (os == "ios") { + return module.platform.environment == "macabi" ? "macCatalyst" : "iOS"; + } + if (os == "macosx" || os == "macos") { + return "macOS"; + } + if (os == "tvos") { + return "tvOS"; + } + if (os == "watchos") { + return "watchOS"; + } + if (os == "xros" || os == "visionos") { + return "visionOS"; + } + return os; +} + +} // namespace + +std::string swiftTypeText(const TypeNode& node, const Module& module) { + return spelling(qualify(node, module)); +} + +std::string swiftIdentifier(const std::string& name) { + return "`" + name + "`"; +} + +std::string availabilityCondition(const Module& module, const Symbol& symbol) { + // Members inherit their enclosing types' availability. + const Version* introduced = nullptr; + for (const Symbol* current = &symbol; current; + current = current->parentId.empty() ? nullptr + : module.find(current->parentId)) { + for (const Availability* availability : + applicableAvailability(module, *current)) { + if (availability->introduced && + (!introduced || isAfter(*availability->introduced, *introduced))) { + introduced = &*availability->introduced; + } + } + } + if (!introduced || (module.platform.minimumVersion && + !isAfter(*introduced, *module.platform.minimumVersion))) { + return ""; + } + return platformName(module) + " " + std::to_string(introduced->major) + "." + + std::to_string(introduced->minor) + + (introduced->patch ? "." + std::to_string(introduced->patch) : "") + + ", *"; +} + +Invocation describeInvocation(const Module& module, const Symbol& symbol, + const Capability& capability) { + Invocation invocation; + const Symbol* owner = + symbol.parentId.empty() ? nullptr : module.find(symbol.parentId); + invocation.owner = owner ? ownerTypeText(module, *owner) : module.name; + invocation.member = symbol.baseName; + invocation.isThrowing = symbol.isThrowing; + invocation.isSettable = symbol.isSettable; + + for (size_t i = 0; i < symbol.parameters.size(); i++) { + invocation.labels.push_back(symbol.parameters[i].label); + invocation.parameterTypes.push_back( + i < capability.parameters.size() + ? typeText(capability.parameters[i], module) + : ""); + } + + bool valueOwner = owner && (owner->kind == SymbolKind::Struct || + owner->kind == SymbolKind::Enum); + bool mutating = std::find(symbol.modifiers.begin(), symbol.modifiers.end(), + "mutating") != symbol.modifiers.end(); + + switch (symbol.kind) { + case SymbolKind::Initializer: + invocation.form = Invocation::Form::Construct; + invocation.resultType = invocation.owner + (symbol.isFailable ? "?" : ""); + break; + case SymbolKind::InstanceMethod: + invocation.form = Invocation::Form::InstanceMethod; + invocation.needsReceiver = true; + invocation.receiverIsInout = valueOwner && mutating; + break; + case SymbolKind::TypeMethod: + invocation.form = Invocation::Form::StaticMethod; + break; + case SymbolKind::Function: + invocation.form = Invocation::Form::Function; + break; + case SymbolKind::InstanceProperty: + invocation.form = Invocation::Form::InstanceProperty; + invocation.needsReceiver = true; + invocation.receiverIsInout = valueOwner && symbol.isSettable; + break; + case SymbolKind::TypeProperty: + invocation.form = Invocation::Form::StaticProperty; + break; + case SymbolKind::Variable: + invocation.form = Invocation::Form::Variable; + break; + case SymbolKind::EnumCase: + invocation.form = Invocation::Form::EnumCase; + invocation.resultType = invocation.owner; + break; + default: + break; + } + if (invocation.resultType.empty()) { + invocation.resultType = typeText(capability.result, module); + } + + invocation.availability = availabilityCondition(module, symbol); + return invocation; +} + +std::string invocationExpression(const Invocation& invocation, + const std::string& receiver, + const std::vector& arguments) { + std::string argumentList; + for (size_t i = 0; i < arguments.size(); i++) { + if (i > 0) { + argumentList += ", "; + } + const std::string& label = + i < invocation.labels.size() ? invocation.labels[i] : ""; + argumentList += label.empty() ? arguments[i] : label + ": " + arguments[i]; + } + + std::string expression; + std::string member = swiftIdentifier(invocation.member); + switch (invocation.form) { + case Invocation::Form::Construct: + expression = invocation.owner + "(" + argumentList + ")"; + break; + case Invocation::Form::InstanceMethod: + expression = receiver + "." + member + "(" + argumentList + ")"; + break; + case Invocation::Form::StaticMethod: + case Invocation::Form::Function: + expression = invocation.owner + "." + member + "(" + argumentList + ")"; + break; + case Invocation::Form::InstanceProperty: + expression = receiver + "." + member; + break; + case Invocation::Form::StaticProperty: + case Invocation::Form::Variable: + case Invocation::Form::EnumCase: + expression = invocation.owner + "." + member; + break; + } + return invocation.isThrowing ? "try " + expression : expression; +} + +std::string assignmentStatement(const Invocation& invocation, + const std::string& receiver, + const std::string& value) { + std::string target = invocation.form == Invocation::Form::InstanceProperty + ? receiver + : invocation.owner; + return target + "." + swiftIdentifier(invocation.member) + " = " + value; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SwiftSource.h b/metadata-generator/src/Swift/SwiftSource.h new file mode 100644 index 000000000..e0c7a49fb --- /dev/null +++ b/metadata-generator/src/Swift/SwiftSource.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +#include "CapabilityClassifier.h" +#include "SwiftIR.h" +#include "SwiftTypes.h" + +namespace Swift { + +// Swift spelling of `node` with module-local types qualified by module name, +// so generated code is immune to shadowing by other imports. +std::string swiftTypeText(const TypeNode& node, const Module& module); + +// The module that declares `symbol`: its cross-import overlay, if any. +std::string declaringModuleName(const Module& module, const Symbol& symbol); + +// `Module.Outer.Inner` for a module-local type. +std::string qualifiedTypeName(const Module& module, const Symbol& symbol); + +// `name` escaped for use as a Swift identifier or member name. +std::string swiftIdentifier(const std::string& name); + +// How generated Swift code invokes a SwiftGenerated symbol. Shared by the +// compiler-validation probes and the thunks, so a probe that type-checks +// vouches for the thunk's call. +struct Invocation { + enum class Form { + Construct, // Owner(args) + InstanceMethod, // receiver.name(args) + StaticMethod, // Owner.name(args) + Function, // Module.name(args) + InstanceProperty, // receiver.name + StaticProperty, // Owner.name + Variable, // Module.name + EnumCase, // Owner.name + }; + + Form form = Form::Function; + // Qualified owner type, or the module name for top-level declarations. + std::string owner; + std::string member; + std::vector labels; + std::vector parameterTypes; + // Qualified result type ("Void" when there is none). + std::string resultType; + bool isThrowing = false; + bool isSettable = false; + // The receiver must be passed `inout` (mutating members and setters of + // value types). + bool receiverIsInout = false; + bool needsReceiver = false; + // "iOS 16.0, *" when the symbol or an enclosing type is introduced after + // the deployment target, empty otherwise. + std::string availability; +}; + +Invocation describeInvocation(const Module& module, const Symbol& symbol, + const Capability& capability); + +// "iOS 16.0, *" when `symbol` or an enclosing type is introduced after the +// deployment target, empty otherwise. +std::string availabilityCondition(const Module& module, const Symbol& symbol); + +// The expression that reads/calls the symbol, including `try`. +std::string invocationExpression(const Invocation& invocation, + const std::string& receiver, + const std::vector& arguments); + +// The statement that assigns `value` to a settable property or variable. +std::string assignmentStatement(const Invocation& invocation, + const std::string& receiver, + const std::string& value); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SwiftTypes.cpp b/metadata-generator/src/Swift/SwiftTypes.cpp new file mode 100644 index 000000000..97a60efad --- /dev/null +++ b/metadata-generator/src/Swift/SwiftTypes.cpp @@ -0,0 +1,663 @@ +#include "SwiftTypes.h" + +#include + +#include "FragmentTokens.h" + +namespace Swift { + +using namespace FragmentTokens; + +const std::string& TypeNode::usr() const { + static const std::string empty; + return components.empty() ? empty : components.back().usr; +} + +bool TypeNode::hasAttribute(const std::string& attribute) const { + for (const auto& candidate : attributes) { + if (candidate == attribute) { + return true; + } + } + return false; +} + +const char* toString(TypeNode::Kind kind) { + switch (kind) { + case TypeNode::Kind::Nominal: + return "nominal"; + case TypeNode::Kind::GenericParameter: + return "genericParameter"; + case TypeNode::Kind::Optional: + return "optional"; + case TypeNode::Kind::ImplicitlyUnwrappedOptional: + return "implicitlyUnwrappedOptional"; + case TypeNode::Kind::Array: + return "array"; + case TypeNode::Kind::Dictionary: + return "dictionary"; + case TypeNode::Kind::Tuple: + return "tuple"; + case TypeNode::Kind::Function: + return "function"; + case TypeNode::Kind::Metatype: + return "metatype"; + case TypeNode::Kind::Existential: + return "existential"; + case TypeNode::Kind::Opaque: + return "opaque"; + case TypeNode::Kind::Composition: + return "composition"; + case TypeNode::Kind::Void: + return "void"; + case TypeNode::Kind::Unknown: + return "unknown"; + } + return "unknown"; +} + +namespace { + +bool isWord(const Token& token, llvm::StringRef word) { + return (token.type == Token::Type::Word || token.isFragment("keyword")) && + token.text == word; +} + +bool isName(const Token& token) { + return token.isFragment("typeIdentifier") || + token.isFragment("genericParameter") || + token.isFragment("identifier") || + (token.isFragment("keyword") && + (token.text == "Self" || token.text == "Any" || + token.text == "AnyObject")) || + (token.type == Token::Type::Word && !token.text.empty() && + (llvm::isAlpha(token.text[0]) || token.text[0] == '_')); +} + +class TypeParser { + public: + TypeParser(const Tokens& tokens, const std::set& genericNames) + : _tokens(tokens), _genericNames(genericNames) {} + + TypeNode parse(bool* complete) { + TypeNode node = parseType(); + skipSpaces(); + if (complete) { + *complete = !_failed && atEnd(); + } + return node; + } + + private: + bool atEnd() const { return _pos >= _tokens.size(); } + const Token& peek() const { return _tokens[_pos]; } + + void skipSpaces() { + while (!atEnd() && peek().type == Token::Type::Space) { + _pos++; + } + } + + bool acceptPunct(char c) { + skipSpaces(); + if (!atEnd() && peek().isPunct(c)) { + _pos++; + return true; + } + return false; + } + + TypeNode unknown(std::string text) { + _failed = true; + TypeNode node; + node.kind = TypeNode::Kind::Unknown; + node.text = std::move(text); + return node; + } + + std::string consumeAttribute() { + std::string attribute = peek().text; + bool abuts = !attribute.empty() && !llvm::isSpace(attribute.back()); + attribute = llvm::StringRef(attribute).trim().str(); + _pos++; + if (abuts && !atEnd() && peek().isPunct('(')) { + int depth = 0; + while (!atEnd()) { + const Token& token = _tokens[_pos++]; + attribute += token.text; + if (opens(token)) { + depth++; + } else if (closes(token) && --depth == 0) { + break; + } + } + } + return attribute; + } + + TypeNode parseType() { + std::vector attributes; + std::vector modifiers; + while (true) { + skipSpaces(); + if (atEnd()) { + break; + } + const Token& token = peek(); + if (token.isFragment("attribute") || + (token.isFragment("keyword") && + llvm::StringRef(token.text).startswith("nonisolated")) || + isWord(token, "nonisolated")) { + // `nonisolated(nonsending)` qualifies closure types like an attribute. + attributes.push_back(consumeAttribute()); + } else if (isWord(token, "inout") || isWord(token, "borrowing") || + isWord(token, "consuming") || isWord(token, "sending") || + isWord(token, "__owned") || isWord(token, "__shared") || + isWord(token, "isolated") || isWord(token, "repeat") || + isWord(token, "each")) { + modifiers.push_back(token.text); + _pos++; + } else { + break; + } + } + + TypeNode node; + skipSpaces(); + if (!atEnd() && (isWord(peek(), "some") || isWord(peek(), "any"))) { + bool opaque = peek().text == "some"; + _pos++; + node.kind = opaque ? TypeNode::Kind::Opaque : TypeNode::Kind::Existential; + node.children.push_back(parseComposition()); + } else { + node = parseComposition(); + } + + node.attributes.insert(node.attributes.begin(), attributes.begin(), + attributes.end()); + if (!modifiers.empty()) { + node.modifier = llvm::join(modifiers, " "); + } + if (llvm::StringRef(node.modifier).contains("each")) { + // Parameter packs are not modeled. + _failed = true; + } + return node; + } + + TypeNode parseComposition() { + TypeNode first = parsePostfix(parsePrimary()); + if (!acceptPunct('&')) { + return first; + } + TypeNode composition; + composition.kind = TypeNode::Kind::Composition; + composition.children.push_back(std::move(first)); + do { + composition.children.push_back(parsePostfix(parsePrimary())); + } while (acceptPunct('&')); + return composition; + } + + TypeNode parsePostfix(TypeNode node) { + while (true) { + if (atEnd()) { + return node; + } + const Token& token = peek(); + if (token.isPunct('?') || token.isPunct('!')) { + TypeNode wrapper; + wrapper.kind = token.isPunct('?') + ? TypeNode::Kind::Optional + : TypeNode::Kind::ImplicitlyUnwrappedOptional; + wrapper.children.push_back(std::move(node)); + node = std::move(wrapper); + _pos++; + } else if (token.type == Token::Type::Word && + (token.text == ".Type" || token.text == ".Protocol")) { + TypeNode wrapper; + wrapper.kind = TypeNode::Kind::Metatype; + wrapper.text = token.text.substr(1); + wrapper.children.push_back(std::move(node)); + node = std::move(wrapper); + _pos++; + } else { + return node; + } + } + } + + // Parses `(`-delimited elements; the opening parenthesis is consumed. + std::vector parseParenthesized(std::vector& labels, + bool& anyLabel) { + std::vector elements; + anyLabel = false; + skipSpaces(); + if (acceptPunct(')')) { + return elements; + } + while (true) { + skipSpaces(); + std::string label; + // `label: Type` inside tuples (and argument-labeled closure types). + if (!atEnd() && _pos + 1 < _tokens.size() && + (peek().type == Token::Type::Word || + peek().isFragment("identifier") || + peek().isFragment("externalParam") || + peek().isFragment("internalParam"))) { + size_t lookahead = _pos + 1; + while (lookahead < _tokens.size() && + _tokens[lookahead].type == Token::Type::Space) { + lookahead++; + } + if (lookahead < _tokens.size() && _tokens[lookahead].isPunct(':')) { + label = peek().text; + anyLabel = true; + _pos = lookahead + 1; + } + } + labels.push_back(label); + elements.push_back(parseType()); + if (acceptPunct(',')) { + continue; + } + if (acceptPunct(')')) { + return elements; + } + _failed = true; + return elements; + } + } + + TypeNode parsePrimary() { + skipSpaces(); + if (atEnd()) { + return unknown(""); + } + const Token& token = peek(); + + if (token.isPunct('(')) { + _pos++; + std::vector labels; + bool anyLabel = false; + std::vector elements = parseParenthesized(labels, anyLabel); + + skipSpaces(); + bool isFunction = + !atEnd() && + (isWord(peek(), "async") || isWord(peek(), "throws") || + isWord(peek(), "rethrows") || peek().type == Token::Type::Arrow); + if (isFunction) { + TypeNode function; + function.kind = TypeNode::Kind::Function; + function.children = std::move(elements); + while (true) { + skipSpaces(); + if (atEnd()) { + break; + } + if (isWord(peek(), "async")) { + function.isAsync = true; + _pos++; + } else if (isWord(peek(), "throws") || isWord(peek(), "rethrows")) { + function.isThrowing = true; + _pos++; + if (!atEnd() && peek().isPunct('(')) { + _pos++; + function.thrownType.push_back(parseType()); + if (!acceptPunct(')')) { + _failed = true; + } + } + } else { + break; + } + } + skipSpaces(); + if (atEnd() || peek().type != Token::Type::Arrow) { + _failed = true; + return function; + } + _pos++; + function.result.push_back(parseType()); + return function; + } + + if (elements.empty()) { + TypeNode voidNode; + voidNode.kind = TypeNode::Kind::Void; + return voidNode; + } + if (elements.size() == 1 && !anyLabel) { + return std::move(elements.front()); + } + TypeNode tuple; + tuple.kind = TypeNode::Kind::Tuple; + tuple.children = std::move(elements); + tuple.labels = std::move(labels); + return tuple; + } + + if (token.isPunct('[')) { + _pos++; + TypeNode key = parseType(); + TypeNode node; + if (acceptPunct(':')) { + node.kind = TypeNode::Kind::Dictionary; + node.children.push_back(std::move(key)); + node.children.push_back(parseType()); + } else { + node.kind = TypeNode::Kind::Array; + node.children.push_back(std::move(key)); + } + if (!acceptPunct(']')) { + _failed = true; + } + return node; + } + + if (isName(token)) { + return parseNominal(); + } + + _pos++; + return unknown(token.text); + } + + TypeNode parseNominal() { + TypeNode node; + node.kind = TypeNode::Kind::Nominal; + while (true) { + const Token& token = peek(); + TypeNode::Component component; + component.name = token.text; + component.usr = token.precise; + _pos++; + if (!atEnd() && peek().isPunct('<')) { + _pos++; + do { + component.arguments.push_back(parseType()); + } while (acceptPunct(',')); + if (!acceptPunct('>')) { + _failed = true; + } + } + node.components.push_back(std::move(component)); + + if (atEnd() || peek().type != Token::Type::Word) { + break; + } + llvm::StringRef word = peek().text; + if (word == ".") { + // `Outer` "." `Inner`, the inner name being its own fragment. + if (_pos + 1 < _tokens.size() && isName(_tokens[_pos + 1])) { + _pos++; + continue; + } + break; + } + if (word.startswith(".") && word != ".Type" && word != ".Protocol" && + word.size() > 1 && (llvm::isAlpha(word[1]) || word[1] == '_')) { + // `Outer.Inner` written as one text run after the outer name. + for (llvm::StringRef rest = word.drop_front(); !rest.empty();) { + auto split = rest.split('.'); + node.components.push_back( + TypeNode::Component{split.first.str(), "", {}}); + rest = split.second; + } + _pos++; + } + break; + } + return normalize(std::move(node)); + } + + TypeNode normalize(TypeNode node) { + const std::string& first = node.components.front().name; + if (first == "Self" || _genericNames.count(first)) { + node.kind = TypeNode::Kind::GenericParameter; + return node; + } + if (node.components.size() != 1) { + return node; + } + TypeNode::Component& component = node.components.front(); + auto wrap = [&](TypeNode::Kind kind, size_t arity) -> TypeNode { + if (component.arguments.size() != arity) { + return node; + } + TypeNode wrapper; + wrapper.kind = kind; + wrapper.children = std::move(component.arguments); + return wrapper; + }; + const std::string& usr = component.usr; + if (usr == KnownTypes::kOptional) { + return wrap(TypeNode::Kind::Optional, 1); + } + if (usr == KnownTypes::kArray) { + return wrap(TypeNode::Kind::Array, 1); + } + if (usr == KnownTypes::kDictionary) { + return wrap(TypeNode::Kind::Dictionary, 2); + } + if (usr == KnownTypes::kVoid || (usr.empty() && component.name == "Void")) { + TypeNode voidNode; + voidNode.kind = TypeNode::Kind::Void; + return voidNode; + } + if (component.name == "Any" || component.name == "AnyObject") { + TypeNode existential; + existential.kind = TypeNode::Kind::Existential; + existential.children.push_back(std::move(node)); + return existential; + } + return node; + } + + const Tokens& _tokens; + const std::set& _genericNames; + size_t _pos = 0; + bool _failed = false; +}; + +std::string spellComponents(const TypeNode& node) { + std::string out; + for (size_t i = 0; i < node.components.size(); i++) { + const auto& component = node.components[i]; + if (i > 0) { + out += "."; + } + out += component.name; + if (!component.arguments.empty()) { + out += "<"; + for (size_t j = 0; j < component.arguments.size(); j++) { + if (j > 0) { + out += ", "; + } + out += spelling(component.arguments[j]); + } + out += ">"; + } + } + return out; +} + +// Postfix operators bind tighter than function arrows and compositions. +std::string spellOperand(const TypeNode& node) { + std::string text = spelling(node); + bool needsParens = node.kind == TypeNode::Kind::Function || + node.kind == TypeNode::Kind::Composition || + node.kind == TypeNode::Kind::Existential || + node.kind == TypeNode::Kind::Opaque; + return needsParens ? "(" + text + ")" : text; +} + +} // namespace + +TypeNode parseType(const TypeRef& type, + const std::set& genericNames, bool* complete) { + Tokens tokens = tokenize(type.fragments); + TypeParser parser(tokens, genericNames); + return parser.parse(complete); +} + +std::string spelling(const TypeNode& node) { + std::string prefix; + for (const auto& attribute : node.attributes) { + prefix += attribute + " "; + } + if (!node.modifier.empty()) { + prefix += node.modifier + " "; + } + + std::string body; + switch (node.kind) { + case TypeNode::Kind::Nominal: + case TypeNode::Kind::GenericParameter: + body = spellComponents(node); + break; + case TypeNode::Kind::Optional: + body = spellOperand(node.children[0]) + "?"; + break; + case TypeNode::Kind::ImplicitlyUnwrappedOptional: + body = spellOperand(node.children[0]) + "!"; + break; + case TypeNode::Kind::Array: + body = "[" + spelling(node.children[0]) + "]"; + break; + case TypeNode::Kind::Dictionary: + body = "[" + spelling(node.children[0]) + ": " + + spelling(node.children[1]) + "]"; + break; + case TypeNode::Kind::Tuple: { + body = "("; + for (size_t i = 0; i < node.children.size(); i++) { + if (i > 0) { + body += ", "; + } + if (i < node.labels.size() && !node.labels[i].empty()) { + body += node.labels[i] + ": "; + } + body += spelling(node.children[i]); + } + body += ")"; + break; + } + case TypeNode::Kind::Function: { + body = "("; + for (size_t i = 0; i < node.children.size(); i++) { + if (i > 0) { + body += ", "; + } + body += spelling(node.children[i]); + } + body += ")"; + if (node.isAsync) { + body += " async"; + } + if (node.isThrowing) { + body += " throws"; + if (!node.thrownType.empty()) { + body += "(" + spelling(node.thrownType[0]) + ")"; + } + } + body += " -> " + (node.result.empty() ? std::string("Void") + : spelling(node.result[0])); + break; + } + case TypeNode::Kind::Metatype: + body = spellOperand(node.children[0]) + "." + + (node.text.empty() ? "Type" : node.text); + break; + case TypeNode::Kind::Existential: + if (node.children.size() == 1 && + node.children[0].kind == TypeNode::Kind::Nominal && + node.children[0].components.size() == 1 && + (node.children[0].components[0].name == "Any" || + node.children[0].components[0].name == "AnyObject")) { + body = node.children[0].components[0].name; + } else { + body = "any " + spelling(node.children[0]); + } + break; + case TypeNode::Kind::Opaque: + body = "some " + spelling(node.children[0]); + break; + case TypeNode::Kind::Composition: { + for (size_t i = 0; i < node.children.size(); i++) { + if (i > 0) { + body += " & "; + } + body += spelling(node.children[i]); + } + break; + } + case TypeNode::Kind::Void: + body = "Void"; + break; + case TypeNode::Kind::Unknown: + body = node.text; + break; + } + return prefix + body; +} + +std::string qualifiedNameFromUSR(const std::string& usr) { + static const std::pair standard[] = { + {"s:Sb", "Swift.Bool"}, {"s:Si", "Swift.Int"}, + {"s:Su", "Swift.UInt"}, {"s:Sf", "Swift.Float"}, + {"s:Sd", "Swift.Double"}, {"s:SS", "Swift.String"}, + {"s:SJ", "Swift.Character"}, {"s:Sq", "Swift.Optional"}, + {"s:Sa", "Swift.Array"}, {"s:SD", "Swift.Dictionary"}, + {"s:Sh", "Swift.Set"}, + }; + for (const auto& entry : standard) { + if (usr == entry.first) { + return entry.second; + } + } + // `s:` followed by length-prefixed identifiers (module first) and one + // declaration-kind letter: s:10Foundation4DataV -> Foundation.Data. + llvm::StringRef rest = usr; + if (!rest.consume_front("s:")) { + return ""; + } + std::vector names; + // A leading `s` abbreviates the Swift module: s:s5Int64V. + if (rest.consume_front("s")) { + names.push_back("Swift"); + } + while (!rest.empty() && llvm::isDigit(rest.front())) { + size_t length = 0; + while (!rest.empty() && llvm::isDigit(rest.front())) { + length = length * 10 + (rest.front() - '0'); + rest = rest.drop_front(); + } + if (length == 0 || length > rest.size()) { + return ""; + } + names.push_back(rest.take_front(length).str()); + rest = rest.drop_front(length); + } + if (names.size() < 2 || rest.size() != 1 || + !llvm::StringRef("VCOPa").contains(rest.front())) { + return ""; + } + return llvm::join(names, "."); +} + +std::set genericNamesInScope(const Module& module, + const Symbol& symbol) { + std::set names; + for (const Symbol* current = &symbol; current; + current = current->parentId.empty() ? nullptr + : module.find(current->parentId)) { + for (const auto& parameter : current->genericParameters) { + names.insert(parameter.name); + } + } + return names; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SwiftTypes.h b/metadata-generator/src/Swift/SwiftTypes.h new file mode 100644 index 000000000..8b7d64617 --- /dev/null +++ b/metadata-generator/src/Swift/SwiftTypes.h @@ -0,0 +1,118 @@ +#pragma once + +#include +#include +#include + +#include "SwiftIR.h" + +namespace Swift { + +// A Swift type as a tree, parsed from a TypeRef's fragments. +struct TypeNode { + enum class Kind { + // A named type, possibly nested (`AttributedString.Index`) and generic + // (`Binding`). Optional, Array and Dictionary spelled as named + // generics are normalized to their own kinds. + Nominal, + // A generic parameter in scope, `Self`, or a member of one (`T.Value`). + GenericParameter, + Optional, + ImplicitlyUnwrappedOptional, + Array, + Dictionary, + Tuple, + Function, + Metatype, + // `any P` (also `Any`, `AnyObject`). + Existential, + // `some P`. + Opaque, + // `P & Q`. + Composition, + Void, + // Anything the parser does not model (parameter packs, `~Copyable`); + // `text` holds the spelling. + Unknown, + }; + + struct Component { + std::string name; + std::string usr; + std::vector arguments; + }; + + Kind kind = Kind::Unknown; + // Nominal: one entry per dot-separated name; GenericParameter: its name(s). + std::vector components; + // Element/wrapped types, tuple elements, function parameters, composition + // members, dictionary key and value. + std::vector children; + std::vector labels; + // Function result; empty for other kinds. + std::vector result; + std::vector thrownType; + bool isAsync = false; + bool isThrowing = false; + // "@escaping", "@Sendable", "@MainActor", "@convention(c)", ... + std::vector attributes; + // "inout", "borrowing", "consuming", "sending", "repeat each". + std::string modifier; + std::string text; + + // USR of the last component (Nominal only). + const std::string& usr() const; + bool hasAttribute(const std::string& attribute) const; +}; + +const char* toString(TypeNode::Kind kind); + +// Parses `type`. Names in `genericNames` (and `Self`) are generic parameters. +// `complete` is cleared when trailing tokens could not be parsed; the +// returned node then describes only a prefix. +TypeNode parseType(const TypeRef& type, + const std::set& genericNames, + bool* complete = nullptr); + +// Canonical Swift spelling of `node`. +std::string spelling(const TypeNode& node); + +// Qualified name encoded in a simple nominal USR ("s:10Foundation4DataV" -> +// "Foundation.Data"), or "" when the USR is not of that shape. +std::string qualifiedNameFromUSR(const std::string& usr); + +// Generic parameter names in scope for `symbol`: its own and those of every +// enclosing declaration. +std::set genericNamesInScope(const Module& module, + const Symbol& symbol); + +// Well-known USRs of standard library and Foundation types. +namespace KnownTypes { +constexpr const char* kBool = "s:Sb"; +constexpr const char* kInt = "s:Si"; +constexpr const char* kInt8 = "s:s4Int8V"; +constexpr const char* kInt16 = "s:s5Int16V"; +constexpr const char* kInt32 = "s:s5Int32V"; +constexpr const char* kInt64 = "s:s5Int64V"; +constexpr const char* kUInt = "s:Su"; +constexpr const char* kUInt8 = "s:s5UInt8V"; +constexpr const char* kUInt16 = "s:s6UInt16V"; +constexpr const char* kUInt32 = "s:s6UInt32V"; +constexpr const char* kUInt64 = "s:s6UInt64V"; +constexpr const char* kFloat = "s:Sf"; +constexpr const char* kDouble = "s:Sd"; +constexpr const char* kCGFloat = "s:14CoreFoundation7CGFloatV"; +constexpr const char* kString = "s:SS"; +constexpr const char* kCharacter = "s:SJ"; +constexpr const char* kOptional = "s:Sq"; +constexpr const char* kArray = "s:Sa"; +constexpr const char* kDictionary = "s:SD"; +constexpr const char* kSet = "s:Sh"; +constexpr const char* kVoid = "s:s4Voida"; +constexpr const char* kURL = "s:10Foundation3URLV"; +constexpr const char* kData = "s:10Foundation4DataV"; +constexpr const char* kDate = "s:10Foundation4DateV"; +constexpr const char* kError = "s:s5ErrorP"; +} // namespace KnownTypes + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SymbolGraphLoader.cpp b/metadata-generator/src/Swift/SymbolGraphLoader.cpp index 4b4d63469..6af364286 100644 --- a/metadata-generator/src/Swift/SymbolGraphLoader.cpp +++ b/metadata-generator/src/Swift/SymbolGraphLoader.cpp @@ -12,6 +12,8 @@ #include #include +#include "FragmentTokens.h" + namespace Swift { namespace { @@ -67,132 +69,8 @@ bool isGraphFileName(llvm::StringRef fileName) { } // --- Declaration fragment parsing ------------------------------------------- -// -// Symbol graphs carry most semantics (effects, settability, labels, failable -// initializers, actor-ness) only inside `declarationFragments`, where -// structural punctuation is mixed into "text" fragments (e.g. "?) -> "). -// Text fragments are therefore split into single structural tokens before -// parsing. - -struct Token { - enum class Type { Fragment, Punct, Space, Word, Arrow }; - Type type; - // Fragment kind for Fragment tokens, "text" otherwise. - std::string kind; - std::string text; - std::string precise; - - bool isPunct(char c) const { - return type == Type::Punct && text.size() == 1 && text[0] == c; - } - bool isFragment(llvm::StringRef fragmentKind) const { - return type == Type::Fragment && kind == fragmentKind; - } - bool isKeyword(llvm::StringRef keyword) const { - return isFragment("keyword") && text == keyword; - } -}; - -using Tokens = std::vector; - -Tokens tokenize(const Fragments& fragments) { - Tokens tokens; - for (const auto& fragment : fragments) { - // Custom attributes (global actors, property wrappers) arrive as an "@" - // fragment followed by the attribute type's name. - if (fragment.kind == "attribute" && !tokens.empty() && - tokens.back().isFragment("attribute") && tokens.back().text == "@") { - tokens.back().text += fragment.spelling; - tokens.back().precise = fragment.preciseIdentifier; - continue; - } - if (fragment.kind != "text") { - tokens.push_back(Token{Token::Type::Fragment, fragment.kind, - fragment.spelling, fragment.preciseIdentifier}); - continue; - } - - llvm::StringRef text = fragment.spelling; - // Some attributes arrive as plain text ("@backDeployed(before: iOS - // 17.0)\n", "@abi(func f(...))"). Only the name becomes the attribute - // token; its argument list is tokenized normally so consumeAttribute can - // match the parentheses, which may close in a later fragment. - if (text.ltrim().startswith("@")) { - llvm::StringRef rest = text.ltrim(); - size_t nameEnd = 1; - while (nameEnd < rest.size() && - (llvm::isAlnum(rest[nameEnd]) || rest[nameEnd] == '_')) { - nameEnd++; - } - tokens.push_back(Token{Token::Type::Fragment, "attribute", - rest.take_front(nameEnd).str(), ""}); - text = rest.drop_front(nameEnd); - } - - size_t i = 0; - while (i < text.size()) { - char c = text[i]; - if (llvm::isSpace(c)) { - size_t end = i; - while (end < text.size() && llvm::isSpace(text[end])) { - end++; - } - tokens.push_back( - Token{Token::Type::Space, "text", text.slice(i, end).str(), ""}); - i = end; - } else if (text.substr(i).startswith("->")) { - tokens.push_back(Token{Token::Type::Arrow, "text", "->", ""}); - i += 2; - } else if (llvm::StringRef("()[]<>,:?!={}&").contains(c)) { - tokens.push_back( - Token{Token::Type::Punct, "text", std::string(1, c), ""}); - i++; - } else { - size_t end = i; - while (end < text.size() && !llvm::isSpace(text[end]) && - !llvm::StringRef("()[]<>,:?!={}&").contains(text[end]) && - !text.substr(end).startswith("->")) { - end++; - } - tokens.push_back( - Token{Token::Type::Word, "text", text.slice(i, end).str(), ""}); - i = end; - } - } - } - return tokens; -} - -bool opens(const Token& token) { - return token.isPunct('(') || token.isPunct('[') || token.isPunct('<'); -} - -bool closes(const Token& token) { - return token.isPunct(')') || token.isPunct(']') || token.isPunct('>'); -} -TypeRef makeTypeRef(Tokens::const_iterator begin, Tokens::const_iterator end) { - while (begin != end && begin->type == Token::Type::Space) { - ++begin; - } - while (end != begin && std::prev(end)->type == Token::Type::Space) { - --end; - } - - TypeRef type; - for (auto it = begin; it != end; ++it) { - type.spelling += it->text; - if (it->type == Token::Type::Fragment) { - type.fragments.push_back(Fragment{it->kind, it->text, it->precise}); - } else if (!type.fragments.empty() && - type.fragments.back().kind == "text") { - type.fragments.back().spelling += it->text; - } else { - type.fragments.push_back(Fragment{"text", it->text, ""}); - } - } - return type; -} +using namespace FragmentTokens; bool isVoid(const TypeRef& type) { return type.spelling == "()" || type.spelling == "Void"; @@ -1291,9 +1169,20 @@ void SymbolGraphLoader::addBuffer(llvm::StringRef json, } }; + // `@.symbols.json`: graphs of cross-import overlays + // carry the overlay's name only in the file name. + std::string declaringModule = llvm::StringRef(path::filename(displayName)) + .split('@') + .first.split('.') + .first.str(); + if (declaringModule == moduleName) { + declaringModule.clear(); + } + forEachObject(symbolsText, "symbols", [&](const Object& object) { auto symbol = parseSymbol(object, displayName, _diagnostics); if (symbol) { + symbol->declaringModule = declaringModule; insertSymbol(module, std::move(*symbol), displayName); } }); diff --git a/metadata-generator/src/main.cpp b/metadata-generator/src/main.cpp index df30e572c..f8cdf6bd2 100644 --- a/metadata-generator/src/main.cpp +++ b/metadata-generator/src/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -18,6 +19,10 @@ #include "Meta/Filters/ModulesBlacklist.h" #include "Meta/Filters/RemoveDuplicateMembersFilter.h" #include "Meta/Filters/ResolveGlobalNamesCollisionsFilter.h" +#include "Swift/CapabilityClassifier.h" +#include "Swift/CoverageReport.h" +#include "Swift/ProbeEmitter.h" +#include "Swift/ProbeVerifier.h" #include "Swift/SymbolGraphLoader.h" #include "TypeScript/DefinitionWriter.h" #include "TypeScript/DocSetManager.h" @@ -48,6 +53,50 @@ llvm::cl::opt cla_swiftIROutputDir( llvm::cl::desc("Directory to write the Swift IR (.swift-ir.json) " "for each imported module"), llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftDeploymentTarget( + "swift-deployment-target", + llvm::cl::desc("Deployment target (e.g. 15.0) for Swift availability " + "decisions; defaults to the minimum version recorded in " + "the symbol graphs"), + llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftVerify( + "swift-verify", + llvm::cl::desc("Type-check the Swift-generated surface with the Swift " + "compiler and demote every declaration it rejects"), + llvm::cl::init(false)); +llvm::cl::opt cla_swiftCompiler( + "swift-compiler", + llvm::cl::desc("Swift compiler command for --swift-verify"), + llvm::cl::init("xcrun swiftc")); +llvm::cl::opt cla_swiftSDK( + "swift-sdk", llvm::cl::desc("SDK path for --swift-verify"), + llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftTarget( + "swift-target", llvm::cl::desc("Target triple for --swift-verify"), + llvm::cl::value_desc("")); +llvm::cl::list cla_swiftSearchPaths( + "swift-search-path", + llvm::cl::desc("Module search path (-I) for --swift-verify"), + llvm::cl::value_desc("")); +llvm::cl::list cla_swiftFrameworkSearchPaths( + "swift-framework-search-path", + llvm::cl::desc("Framework search path (-F) for --swift-verify"), + llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftWorkDir( + "swift-work-dir", + llvm::cl::desc("Scratch directory for --swift-verify (default: a " + "temporary directory)"), + llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftCoverageOutputDir( + "swift-coverage-output", + llvm::cl::desc("Directory to write Swift coverage reports " + "(.coverage.json)"), + llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftProbeOutputDir( + "swift-probe-output", + llvm::cl::desc("Directory to write compiler-validation probes " + "(.probe.swift and .probe-map.json)"), + llvm::cl::value_desc("")); class MetaGenerationConsumer : public clang::ASTConsumer { public: @@ -282,6 +331,25 @@ int main(int argc, const char** argv) return true; }; + if (!cla_swiftDeploymentTarget.empty()) { + Swift::Version target; + llvm::StringRef rest = cla_swiftDeploymentTarget.getValue(); + auto major = rest.split('.'); + auto minor = major.second.split('.'); + if (major.first.getAsInteger(10, target.major) || + (!minor.first.empty() && + minor.first.getAsInteger(10, target.minor)) || + (!minor.second.empty() && + minor.second.getAsInteger(10, target.patch))) { + std::cerr << "error: invalid --swift-deployment-target '" + << cla_swiftDeploymentTarget << "'" << std::endl; + return 1; + } + for (auto& entry : swiftModules.modules) { + entry.second.platform.minimumVersion = target; + } + } + for (const auto& entry : swiftModules.modules) { const Swift::Module& module = entry.second; if (!cla_outputDtsFolder.empty()) { @@ -295,6 +363,77 @@ int main(int argc, const char** argv) module.name + ".swift-ir.json", Swift::dumpModuleJSON(module)); } + if (cla_swiftCoverageOutputDir.empty() && + cla_swiftProbeOutputDir.empty()) { + continue; + } + Swift::Classification classification; + int compilerRuns = -1; + if (cla_swiftVerify) { + Swift::VerifyOptions options; + options.compiler.clear(); + llvm::SmallVector words; + llvm::StringRef(cla_swiftCompiler).split(words, ' ', -1, false); + for (auto word : words) { + options.compiler.push_back(word.str()); + } + options.sdk = cla_swiftSDK; + options.target = cla_swiftTarget; + options.searchPaths.assign(cla_swiftSearchPaths.begin(), + cla_swiftSearchPaths.end()); + options.frameworkSearchPaths.assign( + cla_swiftFrameworkSearchPaths.begin(), + cla_swiftFrameworkSearchPaths.end()); + options.workDirectory = cla_swiftWorkDir; + if (options.workDirectory.empty()) { + llvm::SmallString<128> temporary; + llvm::sys::fs::createUniqueDirectory("ns-swift-verify", + temporary); + options.workDirectory = temporary.str().str(); + } + Swift::VerifyResult verified = + Swift::verifyWithCompiler(module, options); + if (!verified.failure.empty()) { + std::cerr << "error: swift [verification-failed] " + << module.name << ": " << verified.failure + << std::endl; + swiftFailed = true; + continue; + } + for (const auto& rejection : verified.rejections) { + std::cerr << "warning: swift [compiler-rejected] " + << module.name << " (" << rejection.first + << "): " << rejection.second << std::endl; + } + classification = std::move(verified.classification); + compilerRuns = verified.compilerRuns; + } else { + classification = Swift::classify(module); + } + if (!cla_swiftCoverageOutputDir.empty()) { + swiftFailed |= !writeFile( + cla_swiftCoverageOutputDir, module.name + ".coverage.json", + Swift::coverageJSON(module, classification, compilerRuns)); + } + if (!cla_swiftProbeOutputDir.empty()) { + Swift::ProbeSource probes = + Swift::emitProbes(module, classification); + std::string map; + llvm::raw_string_ostream mapStream(map); + llvm::json::OStream mapJSON(mapStream, 2); + mapJSON.object([&] { + for (const auto& line : probes.lineToSymbol) { + mapJSON.attribute(std::to_string(line.first), line.second); + } + }); + mapStream << "\n"; + mapStream.flush(); + swiftFailed |= + !writeFile(cla_swiftProbeOutputDir, + module.name + ".probe.swift", probes.source); + swiftFailed |= !writeFile(cla_swiftProbeOutputDir, + module.name + ".probe-map.json", map); + } } } diff --git a/metadata-generator/tests/CMakeLists.txt b/metadata-generator/tests/CMakeLists.txt index cb8cbaf87..7d6353b3f 100644 --- a/metadata-generator/tests/CMakeLists.txt +++ b/metadata-generator/tests/CMakeLists.txt @@ -1,11 +1,26 @@ -add_executable(swift-symbolgraph-tests - swift/SymbolGraphLoaderTests.cpp +set(SWIFT_GENERATOR_SOURCES + ${CMAKE_SOURCE_DIR}/src/Swift/CapabilityClassifier.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/CoverageReport.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/FragmentTokens.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/ProbeEmitter.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/ProbeVerifier.cpp ${CMAKE_SOURCE_DIR}/src/Swift/SwiftIR.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/SwiftSource.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/SwiftTypes.cpp ${CMAKE_SOURCE_DIR}/src/Swift/SymbolGraphLoader.cpp ${CMAKE_SOURCE_DIR}/src/TypeScript/SwiftDefinitionWriter.cpp ) + +add_executable(swift-symbolgraph-tests + swift/TestMain.cpp + swift/SymbolGraphLoaderTests.cpp + swift/SwiftTypesTests.cpp + swift/ClassifierTests.cpp + ${SWIFT_GENERATOR_SOURCES} +) target_include_directories(swift-symbolgraph-tests PRIVATE ${CMAKE_SOURCE_DIR}/src) target_compile_definitions(swift-symbolgraph-tests PRIVATE + SWIFT_FIXTURE_DIR="${CMAKE_SOURCE_DIR}/TestFixtures/SwiftDemo" SWIFT_FIXTURE_GRAPHS_DIR="${CMAKE_SOURCE_DIR}/TestFixtures/SwiftDemo/symbolgraphs" SWIFT_SNAPSHOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}/swift/snapshots" ) diff --git a/metadata-generator/tests/swift/ClassifierTests.cpp b/metadata-generator/tests/swift/ClassifierTests.cpp new file mode 100644 index 000000000..d043ddd7a --- /dev/null +++ b/metadata-generator/tests/swift/ClassifierTests.cpp @@ -0,0 +1,335 @@ +#include +#include + +#include "Swift/CapabilityClassifier.h" +#include "Swift/CoverageReport.h" +#include "Swift/ProbeEmitter.h" +#include "Swift/ProbeVerifier.h" +#include "Swift/SwiftSource.h" +#include "TestHarness.h" +#include "TestSupport.h" + +using namespace Swift; +using namespace TestSupport; + +namespace { + +const Classification& classification() { + static Classification result = classify(demo()); + return result; +} + +const Capability* capabilityAt(const std::string& path) { + const Symbol* symbol = symbolAt(demo(), path); + return symbol ? classification().find(symbol->preciseId) : nullptr; +} + +void expectTier(const char* file, int line, const std::string& path, Tier tier, + const std::string& reason = "") { + const Capability* capability = capabilityAt(path); + if (!capability) { + TestHarness::fail(file, line, "no single symbol at " + path); + return; + } + std::string actualReasons = llvm::join(capability->reasons, ","); + if (capability->tier != tier || actualReasons != reason) { + TestHarness::fail(file, line, + path + ": expected " + toString(tier) + "(" + reason + + "), got " + toString(capability->tier) + "(" + + actualReasons + ")"); + } +} + +#define EXPECT_TIER(...) expectTier(__FILE__, __LINE__, __VA_ARGS__) + +} // namespace + +TEST(ClassifyNominalTypes) { + EXPECT_TIER("Demo", Tier::SwiftGenerated); + EXPECT_TIER("Point", Tier::SwiftGenerated); + EXPECT_TIER("Flavor", Tier::SwiftGenerated); + EXPECT_TIER("Counter", Tier::SwiftGenerated); + EXPECT_TIER("Canvas", Tier::SwiftGenerated); + EXPECT_TIER("Greeter", Tier::TypeOnly, "protocol"); + EXPECT_TIER("Measurement", Tier::Unsupported, "enum-associated-values"); + EXPECT_TIER("ShapeError", Tier::Unsupported, "enum-associated-values"); + EXPECT_TIER("Measurement.Unit", Tier::Unsupported, "nested-type"); + EXPECT_TIER("Coordinates", Tier::TypeOnly, "type-alias"); +} + +TEST(ClassifyCallables) { + EXPECT_TIER("Demo.init()", Tier::SwiftGenerated); + EXPECT_TIER("Demo.greet(name:)", Tier::SwiftGenerated); + EXPECT_TIER("Demo.greet(name:times:)", Tier::SwiftGenerated); + EXPECT_TIER("Demo.version", Tier::SwiftGenerated); + EXPECT_TIER("Point.x", Tier::SwiftGenerated); + EXPECT_TIER("Point.init(x:y:)", Tier::SwiftGenerated); + EXPECT_TIER("Point.description", Tier::SwiftGenerated); + EXPECT_TIER("Flavor.vanilla", Tier::SwiftGenerated); + EXPECT_TIER("Flavor.init(rawValue:)", Tier::SwiftGenerated); + EXPECT_TIER("Flavor.hashValue", Tier::SwiftGenerated); + EXPECT_TIER("Polygon.init(name:)", Tier::SwiftGenerated); + EXPECT_TIER("Polygon.describe(_:)", Tier::SwiftGenerated); + EXPECT_TIER("Polygon.make()", Tier::SwiftGenerated); + EXPECT_TIER("Polygon.shared", Tier::SwiftGenerated); + EXPECT_TIER("Ring.expand(by:)", Tier::SwiftGenerated); + EXPECT_TIER("Loader.load(path:)", Tier::Unsupported, + "unbridged-type:Foundation.Data"); + EXPECT_TIER("Loader.modernOnly()", Tier::SwiftGenerated); + EXPECT_TIER("Loader.legacyFetch()", Tier::SwiftGenerated); + EXPECT_TIER("makeDefaultPoint()", Tier::SwiftGenerated); + EXPECT_TIER("defaultFlavor", Tier::SwiftGenerated); + EXPECT_TIER("globalCounter", Tier::SwiftGenerated); + EXPECT_TIER("Counter.init()", Tier::SwiftGenerated); + EXPECT_TIER("Counter.label()", Tier::SwiftGenerated); +} + +TEST(ClassifyRejections) { + EXPECT_TIER("Greeter.greet(name:)", Tier::TypeOnly, "protocol-requirement"); + EXPECT_TIER("Loader.fetch(url:)", Tier::Unsupported, "async"); + EXPECT_TIER("Loader.wait(seconds:)", Tier::Unsupported, "async"); + EXPECT_TIER("Loader.transform(_:)", Tier::SwiftSpecialized, "generic"); + EXPECT_TIER("Loader.first(of:)", Tier::SwiftSpecialized, "generic"); + EXPECT_TIER("Loader.withCompletion(_:)", Tier::Unsupported, "closure"); + EXPECT_TIER("Loader.each(_:)", Tier::Unsupported, "closure"); + EXPECT_TIER("Loader.update(_:)", Tier::Unsupported, "inout-parameter"); + EXPECT_TIER("Loader.lookup(table:key:)", Tier::Unsupported, "collection"); + EXPECT_TIER("Counter.increment()", Tier::Unsupported, "actor-isolated"); + EXPECT_TIER("Counter.value", Tier::Unsupported, "actor-isolated"); + EXPECT_TIER("Canvas.init()", Tier::Unsupported, "main-actor"); + EXPECT_TIER("Canvas.draw(_:)", Tier::Unsupported, "main-actor"); + EXPECT_TIER("Ring.+(_:_:)", Tier::Unsupported, "operator"); + EXPECT_TIER("Polygon.subscript(_:)", Tier::Unsupported, "subscript"); + EXPECT_TIER("String.shouted", Tier::Unsupported, "external-type-extension"); + EXPECT_TIER("Measurement.isNone", Tier::Unsupported, "owner-not-bridged"); + EXPECT_TIER("Flavor.hash(into:)", Tier::Unsupported, "inout-parameter"); +} + +TEST(ClassifyBridges) { + const Capability* describe = capabilityAt("Polygon.describe(_:)"); + REQUIRE(describe && describe->parameters.size() == 1); + CHECK(describe->parameters[0].bridge == Bridge::ClassHandle); + CHECK(describe->parameters[0].optional); + CHECK(describe->result.bridge == Bridge::String); + + const Capability* rawValue = capabilityAt("Flavor.init(rawValue:)"); + REQUIRE(rawValue); + CHECK(rawValue->result.bridge == Bridge::EnumCase); + CHECK(rawValue->result.optional); + CHECK(rawValue->parameters[0].bridge == Bridge::Integer); + + const Capability* point = capabilityAt("makeDefaultPoint()"); + REQUIRE(point); + CHECK(point->result.bridge == Bridge::StructBox); + CHECK(point->result.symbolId == symbolAt(demo(), "Point")->preciseId); +} + +TEST(ClassifyJsNamesAndOverloads) { + for (const Symbol* overload : symbolsAt(demo(), "Polygon.scale(by:)")) { + const Capability* capability = classification().find(overload->preciseId); + REQUIRE(capability); + CHECK_EQ(capability->jsName, std::string("scale")); + // Double and Int are both JS numbers. + CHECK(capability->ambiguousOverload); + } + CHECK(!capabilityAt("Polygon.scale(x:y:)")->ambiguousOverload); + CHECK(!capabilityAt("Demo.greet(name:)")->ambiguousOverload); + CHECK_EQ(capabilityAt("Demo.greet(name:times:)")->jsName, + std::string("greet")); + CHECK_EQ(capabilityAt("Polygon.init(name:vertexCount:)")->jsName, + std::string("constructor")); + CHECK(!capabilityAt("Polygon.init(name:vertexCount:)")->ambiguousOverload); +} + +TEST(InvocationAvailability) { + const Symbol* modern = symbolAt(demo(), "Loader.modernOnly()"); + REQUIRE(modern); + Invocation invocation = describeInvocation( + demo(), *modern, *classification().find(modern->preciseId)); + CHECK_EQ(invocation.availability, std::string("iOS 16.0, *")); + + const Symbol* old = symbolAt(demo(), "Loader.oldFetch()"); + REQUIRE(old); + Invocation unguarded = + describeInvocation(demo(), *old, *classification().find(old->preciseId)); + CHECK_EQ(unguarded.availability, std::string()); +} + +TEST(CoverageSnapshot) { + checkSnapshot("SwiftDemo.coverage.json", + coverageJSON(demo(), classification())); +} + +TEST(ProbeSnapshot) { + checkSnapshot("SwiftDemo.probe.swift", + emitProbes(demo(), classification()).source); +} + +namespace { + +// Directory holding SwiftDemo.swiftmodule built from the fixture sources, or +// "" when no Swift toolchain is available. +const std::string& fixtureModuleDirectory() { + static std::string directory = [] { + if (!llvm::sys::findProgramByName("xcrun")) { + return std::string(); + } + llvm::SmallString<128> path; + if (llvm::sys::fs::createUniqueDirectory("swift-fixture", path)) { + return std::string(); + } + std::string command = + "xcrun swiftc -emit-module -module-name SwiftDemo " + "-target arm64-apple-ios15.0-simulator " + "-sdk \"$(xcrun --sdk iphonesimulator --show-sdk-path)\" " + "-emit-module-path '" + + path.str().str() + + "/SwiftDemo.swiftmodule' '" SWIFT_FIXTURE_DIR + "'/Sources/SwiftDemo/*.swift"; + auto shell = llvm::sys::findProgramByName("sh"); + if (!shell || + llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}) != 0) { + return std::string(); + } + return path.str().str(); + }(); + return directory; +} + +VerifyOptions fixtureVerifyOptions() { + VerifyOptions options; + options.compiler = {"xcrun", "swiftc"}; + llvm::SmallString<128> sdkLog; + llvm::sys::fs::createTemporaryFile("sdk", "txt", sdkLog); + auto shell = llvm::sys::findProgramByName("sh"); + std::optional redirects[] = { + std::nullopt, llvm::StringRef(sdkLog), std::nullopt}; + llvm::sys::ExecuteAndWait( + *shell, {*shell, "-c", "xcrun --sdk iphonesimulator --show-sdk-path"}, + std::nullopt, redirects); + auto sdk = llvm::MemoryBuffer::getFile(sdkLog); + options.sdk = sdk ? (*sdk)->getBuffer().trim().str() : ""; + llvm::sys::fs::remove(sdkLog); + options.target = "arm64-apple-ios15.0-simulator"; + options.searchPaths = {fixtureModuleDirectory()}; + llvm::SmallString<128> work; + llvm::sys::fs::createUniqueDirectory("swift-verify", work); + options.workDirectory = work.str().str(); + return options; +} + +} // namespace + +TEST(VerifierParsesDiagnostics) { + std::string log = + "/tmp/p.swift:12:7: error: value of type 'X' has no member 'y'\n" + "/tmp/p.swift:12:9: error: second error on the same probe\n" + "/tmp/p.swift:13:1: warning: ignored\n" + "/tmp/other.swift:4:1: error: not ours\n" + "/tmp/p.swift:99:1: error: outside probes\n"; + std::map lines = {{12, "s:sym"}, {13, "s:sym"}}; + std::vector unmapped; + auto rejections = rejectionsFromLog(log, "/tmp/p.swift", lines, unmapped); + REQUIRE(rejections.size() == 1); + CHECK_EQ(rejections.at("s:sym"), + std::string("value of type 'X' has no member 'y'")); + REQUIRE(unmapped.size() == 1); + CHECK_EQ(unmapped[0], std::string("99: outside probes")); +} + +TEST(VerifierAcceptsFixture) { + if (fixtureModuleDirectory().empty()) { + std::cout << " (skipped: no Swift toolchain)" << std::endl; + return; + } + VerifyOptions options = fixtureVerifyOptions(); + VerifyResult result = verifyWithCompiler(demo(), options); + llvm::sys::fs::remove_directories(options.workDirectory); + CHECK_EQ(result.failure, std::string()); + CHECK_EQ(result.compilerRuns, 1); + CHECK(result.rejections.empty()); +} + +TEST(VerifierDemotesWhatTheCompilerRejects) { + if (fixtureModuleDirectory().empty()) { + std::cout << " (skipped: no Swift toolchain)" << std::endl; + return; + } + // An IR that disagrees with the compiler: greet(name:) takes a String, not + // an Int. + Module wrong = demo(); + Symbol* greet = nullptr; + for (auto& entry : wrong.symbols) { + if (llvm::join(entry.second.pathComponents, ".") == "Demo.greet(name:)") { + greet = &entry.second; + } + } + REQUIRE(greet && greet->parameters.size() == 1); + greet->parameters[0].type = + TypeRef{"Int", {Fragment{"typeIdentifier", "Int", "s:Si"}}}; + + VerifyOptions options = fixtureVerifyOptions(); + VerifyResult result = verifyWithCompiler(wrong, options); + llvm::sys::fs::remove_directories(options.workDirectory); + CHECK_EQ(result.failure, std::string()); + CHECK_EQ(result.compilerRuns, 2); + REQUIRE(result.rejections.size() == 1); + CHECK(result.rejections.count(greet->preciseId)); + const Capability* demoted = result.classification.find(greet->preciseId); + REQUIRE(demoted); + CHECK(demoted->tier == Tier::Unsupported); + CHECK( + llvm::StringRef(demoted->reasons.at(0)).startswith("compiler-rejected:")); + + const Symbol* other = symbolAt(demo(), "Demo.greet(name:times:)"); + CHECK(result.classification.find(other->preciseId)->tier == + Tier::SwiftGenerated); +} + +// Builds the fixture module and type-checks the probes against it. +TEST(ProbesTypeCheck) { + auto shell = llvm::sys::findProgramByName("sh"); + auto xcrun = llvm::sys::findProgramByName("xcrun"); + if (!shell || !xcrun) { + std::cout << " (skipped: xcrun not found)" << std::endl; + return; + } + + llvm::SmallString<128> directory; + REQUIRE(!llvm::sys::fs::createUniqueDirectory("swift-probes", directory)); + llvm::SmallString<128> probePath(directory); + llvm::sys::path::append(probePath, "probe.swift"); + { + std::error_code error; + llvm::raw_fd_ostream out(probePath, error, llvm::sys::fs::OF_Text); + REQUIRE(!error); + out << emitProbes(demo(), classification()).source; + } + + std::string dir = directory.str().str(); + std::string command = + "set -e; SDK=$(xcrun --sdk iphonesimulator --show-sdk-path); " + "TARGET=arm64-apple-ios15.0-simulator; " + "xcrun swiftc -emit-module -module-name SwiftDemo -target $TARGET -sdk " + "\"$SDK\" " + "-emit-module-path '" + + dir + + "/SwiftDemo.swiftmodule' '" SWIFT_FIXTURE_DIR + "'/Sources/SwiftDemo/*.swift; " + "xcrun swiftc -typecheck -I '" + + dir + "' -target $TARGET -sdk \"$SDK\" '" + probePath.str().str() + "'"; + llvm::SmallString<128> log(directory); + llvm::sys::path::append(log, "swiftc.log"); + std::optional redirects[] = { + std::nullopt, llvm::StringRef(log), llvm::StringRef(log)}; + int status = llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}, + std::nullopt, redirects); + if (status != 0) { + auto output = llvm::MemoryBuffer::getFile(log); + TestHarness::fail( + __FILE__, __LINE__, + "probes failed to type-check:\n" + + (output ? (*output)->getBuffer().str() : std::string("(no log)"))); + } + llvm::sys::fs::remove_directories(directory); +} diff --git a/metadata-generator/tests/swift/SwiftTypesTests.cpp b/metadata-generator/tests/swift/SwiftTypesTests.cpp new file mode 100644 index 000000000..754291ed1 --- /dev/null +++ b/metadata-generator/tests/swift/SwiftTypesTests.cpp @@ -0,0 +1,215 @@ +#include "Swift/SwiftTypes.h" +#include "TestHarness.h" +#include "TestSupport.h" + +using namespace Swift; +using namespace TestSupport; + +namespace { + +TypeRef ref(std::vector fragments) { + TypeRef type; + for (const auto& fragment : fragments) { + type.spelling += fragment.spelling; + } + type.fragments = std::move(fragments); + return type; +} + +Fragment id(const std::string& name, const std::string& usr = "") { + return Fragment{"typeIdentifier", name, usr}; +} + +Fragment text(const std::string& spelling) { + return Fragment{"text", spelling, ""}; +} + +Fragment keyword(const std::string& spelling) { + return Fragment{"keyword", spelling, ""}; +} + +TypeNode parse(const TypeRef& type, std::set generics = {}, + bool expectComplete = true) { + bool complete = false; + TypeNode node = parseType(type, generics, &complete); + if (complete != expectComplete) { + TestHarness::fail(__FILE__, __LINE__, + "parse of '" + type.spelling + + "' complete=" + std::to_string(complete)); + } + return node; +} + +using Kind = TypeNode::Kind; + +} // namespace + +TEST(TypesOptionalNominal) { + TypeNode node = + parse(ref({id("Polygon", "s:9SwiftDemo7PolygonC"), text("?")})); + CHECK(node.kind == Kind::Optional); + REQUIRE(node.children.size() == 1); + CHECK(node.children[0].kind == Kind::Nominal); + CHECK_EQ(node.children[0].usr(), std::string("s:9SwiftDemo7PolygonC")); + CHECK_EQ(spelling(node), std::string("Polygon?")); +} + +TEST(TypesNamedGenericsNormalize) { + TypeNode optional = parse( + ref({id("Optional", "s:Sq"), text("<"), id("Int", "s:Si"), text(">")})); + CHECK(optional.kind == Kind::Optional); + TypeNode array = parse( + ref({id("Array", "s:Sa"), text("<"), id("Int", "s:Si"), text(">")})); + CHECK(array.kind == Kind::Array); + TypeNode voidType = parse(ref({id("Void", "s:s4Voida")})); + CHECK(voidType.kind == Kind::Void); + TypeNode empty = parse(ref({text("()")})); + CHECK(empty.kind == Kind::Void); +} + +TEST(TypesCollections) { + TypeNode dictionary = parse(ref({text("["), id("String", "s:SS"), text(" : "), + id("Int", "s:Si"), text("]")})); + CHECK(dictionary.kind == Kind::Dictionary); + CHECK_EQ(spelling(dictionary), std::string("[String: Int]")); + + TypeNode array = + parse(ref({text("["), id("Element"), text("]")}), {"Element"}); + CHECK(array.kind == Kind::Array); + CHECK(array.children[0].kind == Kind::GenericParameter); +} + +TEST(TypesFunctions) { + TypeNode completion = parse(ref( + {text("("), id("Result", "s:s6ResultO"), text("<"), id("String", "s:SS"), + text(", "), id("ShapeError", "s:9SwiftDemo10ShapeErrorO"), + text(">) -> "), id("Void", "s:s4Voida")})); + CHECK(completion.kind == Kind::Function); + REQUIRE(completion.children.size() == 1); + CHECK_EQ(completion.children[0].components[0].arguments.size(), size_t(2)); + REQUIRE(completion.result.size() == 1); + CHECK(completion.result[0].kind == Kind::Void); + CHECK_EQ(spelling(completion), + std::string("(Result) -> Void")); + + TypeNode effects = + parse(ref({text("("), keyword("any"), text(" "), id("SerialExecutor"), + text(") "), keyword("throws"), text("("), id("E"), + text(") -> "), id("T")}), + {"E", "T"}); + CHECK(effects.kind == Kind::Function); + CHECK(effects.isThrowing); + REQUIRE(effects.thrownType.size() == 1); + CHECK(effects.thrownType[0].kind == Kind::GenericParameter); + CHECK(effects.children[0].kind == Kind::Existential); + CHECK_EQ(spelling(effects), + std::string("(any SerialExecutor) throws(E) -> T")); + + TypeNode isolated = + parse(ref({Fragment{"attribute", "@", ""}, id("MainActor", "s:ScM"), + text(" ("), id("Message"), text(") "), keyword("async"), + text(" -> "), id("Void", "s:s4Voida")})); + CHECK(isolated.kind == Kind::Function); + CHECK(isolated.isAsync); + CHECK(isolated.hasAttribute("@MainActor")); + + TypeNode optionalClosure = + parse(ref({text("(("), id("URL"), text(", any "), id("Error"), + text(") -> "), id("Bool"), text(")?")})); + CHECK(optionalClosure.kind == Kind::Optional); + CHECK(optionalClosure.children[0].kind == Kind::Function); + CHECK_EQ(spelling(optionalClosure), + std::string("((URL, any Error) -> Bool)?")); +} + +TEST(TypesTuplesKeepLabels) { + TypeNode tuple = + parse(ref({text("(latitude: "), id("Double", "s:Sd"), + text(", longitude: "), id("Double", "s:Sd"), text(")")})); + CHECK(tuple.kind == Kind::Tuple); + CHECK_EQ(llvm::join(tuple.labels, ","), std::string("latitude,longitude")); + CHECK_EQ(spelling(tuple), + std::string("(latitude: Double, longitude: Double)")); +} + +TEST(TypesMemberAndMetatypes) { + TypeNode member = + parse(ref({id("AttributedString"), text("."), id("Index", "s:index")})); + CHECK(member.kind == Kind::Nominal); + CHECK_EQ(member.components.size(), size_t(2)); + CHECK_EQ(member.usr(), std::string("s:index")); + + TypeNode dependent = parse(ref({id("T"), text("."), id("Value")}), {"T"}); + CHECK(dependent.kind == Kind::GenericParameter); + CHECK_EQ(spelling(dependent), std::string("T.Value")); + + TypeNode metatype = parse(ref({id("T"), text(".Type")}), {"T"}); + CHECK(metatype.kind == Kind::Metatype); + CHECK_EQ(spelling(metatype), std::string("T.Type")); + + TypeNode nested = parse(ref({id("KeyPath"), text("<"), id("Scopes"), + text(", "), id("S"), text(".Type>")}), + {"S"}); + CHECK(nested.kind == Kind::Nominal); + CHECK(nested.components[0].arguments[1].kind == Kind::Metatype); +} + +TEST(TypesExistentialsAndCompositions) { + TypeNode opaque = parse(ref({keyword("some"), text(" "), id("View")})); + CHECK(opaque.kind == Kind::Opaque); + + TypeNode composition = + parse(ref({text("any "), id("AnyKeyPath"), text(" & "), id("Sendable")})); + CHECK(composition.kind == Kind::Existential); + CHECK(composition.children[0].kind == Kind::Composition); + CHECK_EQ(spelling(composition), std::string("any AnyKeyPath & Sendable")); + + TypeNode anyType = parse(ref({keyword("Any")})); + CHECK(anyType.kind == Kind::Existential); + CHECK_EQ(spelling(anyType), std::string("Any")); +} + +TEST(TypesIsolationAttributeOnClosure) { + TypeNode node = + parse(ref({keyword("nonisolated"), text("(nonsending) ("), keyword("any"), + text(" "), id("SerialExecutor"), text(") "), keyword("async"), + text(" -> "), id("T")}), + {"T"}); + CHECK(node.kind == Kind::Function); + CHECK(node.hasAttribute("nonisolated(nonsending)")); +} + +TEST(TypesParameterPacksAreIncomplete) { + parse(ref({id("Predicate"), text("")}), + {"Input"}, + /*expectComplete*/ false); +} + +TEST(TypesEveryFixtureTypeParses) { + for (const auto& entry : demo().symbols) { + const Symbol& symbol = entry.second; + std::set generics = genericNamesInScope(demo(), symbol); + std::vector types; + for (const auto& parameter : symbol.parameters) { + types.push_back(¶meter.type); + } + if (symbol.returnType) { + types.push_back(&*symbol.returnType); + } + if (symbol.valueType) { + types.push_back(&*symbol.valueType); + } + if (symbol.aliasedType) { + types.push_back(&*symbol.aliasedType); + } + for (const TypeRef* type : types) { + bool complete = false; + parseType(*type, generics, &complete); + if (!complete) { + TestHarness::fail( + __FILE__, __LINE__, + "incomplete parse of '" + type->spelling + "' in " + symbol.name); + } + } + } +} diff --git a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp index 8d80bc582..6a838ee87 100644 --- a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp +++ b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp @@ -9,63 +9,14 @@ #include "Swift/SymbolGraphLoader.h" #include "TestHarness.h" +#include "TestSupport.h" #include "TypeScript/SwiftDefinitionWriter.h" using namespace Swift; +using namespace TestSupport; namespace { -const ModuleSet& fixture() { - static ModuleSet set = loadSymbolGraphDirectory(SWIFT_FIXTURE_GRAPHS_DIR); - return set; -} - -const Module& demo() { - static const Module empty; - auto it = fixture().modules.find("SwiftDemo"); - return it == fixture().modules.end() ? empty : it->second; -} - -std::vector symbolsAt(const Module& module, - const std::string& path) { - std::vector result; - for (const auto& entry : module.symbols) { - if (llvm::join(entry.second.pathComponents, ".") == path) { - result.push_back(&entry.second); - } - } - return result; -} - -const Symbol* symbolAt(const Module& module, const std::string& path) { - auto symbols = symbolsAt(module, path); - return symbols.size() == 1 ? symbols.front() : nullptr; -} - -std::vector memberNames(const Module& module, - const Symbol& symbol) { - std::vector names; - for (const auto& id : symbol.memberIds) { - if (const Symbol* member = module.find(id)) { - names.push_back(member->name); - } - } - return names; -} - -bool contains(const std::vector& values, - const std::string& value) { - return std::find(values.begin(), values.end(), value) != values.end(); -} - -std::string diagnosticCodes(const std::vector& diagnostics) { - std::vector codes; - for (const auto& diagnostic : diagnostics) { - codes.push_back(diagnostic.code + "(" + diagnostic.message + ")"); - } - return llvm::join(codes, ", "); -} - ModuleSet loadBuffers( const std::vector>& buffers) { SymbolGraphLoader loader; @@ -98,46 +49,13 @@ std::string symbolJSON(const std::string& id, const std::string& kind, rest = split.second; } path += "\"" + name + "\""; - return R"({"kind":{"identifier":")" + kind + R"("},"identifier":{"precise":")" + - id + R"("},"pathComponents":[)" + path + + return R"({"kind":{"identifier":")" + kind + + R"("},"identifier":{"precise":")" + id + R"("},"pathComponents":[)" + + path + R"(],"names":{"title":"x"},"accessLevel":"public","declarationFragments":[)" + declaration + "]}"; } -// Compares `actual` against a checked-in snapshot. NS_UPDATE_SNAPSHOTS=1 -// rewrites the snapshot instead. -void checkSnapshot(const std::string& fileName, const std::string& actual) { - llvm::SmallString<256> snapshotPath(SWIFT_SNAPSHOT_DIR); - llvm::sys::path::append(snapshotPath, fileName); - - if (const char* update = std::getenv("NS_UPDATE_SNAPSHOTS"); - update && *update == '1') { - std::error_code error; - llvm::raw_fd_ostream out(snapshotPath, error, llvm::sys::fs::OF_Text); - REQUIRE(!error); - out << actual; - return; - } - - auto expected = llvm::MemoryBuffer::getFile(snapshotPath, /*IsText*/ true); - if (!expected) { - TestHarness::fail(__FILE__, __LINE__, - "missing snapshot " + snapshotPath.str().str() + - " (run with NS_UPDATE_SNAPSHOTS=1)"); - return; - } - if ((*expected)->getBuffer() != actual) { - llvm::SmallString<256> actualPath(snapshotPath); - actualPath += ".actual"; - std::error_code error; - llvm::raw_fd_ostream out(actualPath, error, llvm::sys::fs::OF_Text); - out << actual; - TestHarness::fail(__FILE__, __LINE__, - "snapshot mismatch: diff " + snapshotPath.str().str() + - " " + actualPath.str().str()); - } -} - } // namespace TEST(LoadsFixtureWithoutDiagnostics) { @@ -632,10 +550,11 @@ TEST(AsyncImportVariantsAreBothKept) { R"(","target":"c:objc(cs)Mini"})"; for (bool asyncFirst : {false, true}) { - std::string symbols = type + "," + (asyncFirst ? async + "," + callback - : callback + "," + async); - ModuleSet set = loadBuffers( - {{"mini.symbols.json", graphJSON(symbols, relationship)}}); + std::string symbols = + type + "," + + (asyncFirst ? async + "," + callback : callback + "," + async); + ModuleSet set = + loadBuffers({{"mini.symbols.json", graphJSON(symbols, relationship)}}); CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); REQUIRE(set.modules.count("Mini")); const Module& module = set.modules.at("Mini"); @@ -668,7 +587,8 @@ TEST(SubclassRedeclarationsAreKeyedByOwner) { accessors + R"json({"kind":"text","spelling":" }"})json", owner); }; - std::string base = subscript("NSArray", R"json({"kind":"keyword","spelling":"get"},)json"); + std::string base = + subscript("NSArray", R"json({"kind":"keyword","spelling":"get"},)json"); std::string mutableVariant = subscript( "NSMutableArray", R"json({"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"set"},)json"); @@ -681,8 +601,8 @@ TEST(SubclassRedeclarationsAreKeyedByOwner) { std::string symbols = type("NSArray") + "," + type("NSMutableArray") + "," + (mutableFirst ? mutableVariant + "," + base : base + "," + mutableVariant); - ModuleSet set = loadBuffers( - {{"mini.symbols.json", graphJSON(symbols, relationships)}}); + ModuleSet set = + loadBuffers({{"mini.symbols.json", graphJSON(symbols, relationships)}}); CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); REQUIRE(set.modules.count("Mini")); const Module& module = set.modules.at("Mini"); @@ -723,8 +643,9 @@ TEST(SkimmerHandlesStringsAndNesting) { std::string symbol = symbolJSON( "s:4Mini1fyyF", "swift.func", "f()", R"json({"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"f"},{"kind":"text","spelling":"()"})json"); - symbol.insert(symbol.size() - 1, - R"json(,"docComment":{"lines":[{"text":"a } ] { [ \"quoted\" \\"}]})json"); + symbol.insert( + symbol.size() - 1, + R"json(,"docComment":{"lines":[{"text":"a } ] { [ \"quoted\" \\"}]})json"); ModuleSet set = loadBuffers({{"mini.symbols.json", graphJSON(symbol, "")}}); CHECK_EQ(diagnosticCodes(set.diagnostics), std::string()); REQUIRE(set.modules.count("Mini")); @@ -754,7 +675,3 @@ TEST(MissingDirectoryIsAnError) { CHECK(set.hasErrors()); CHECK_EQ(set.diagnostics[0].code, std::string("missing-directory")); } - -int main(int argc, char** argv) { - return TestHarness::runAll(argc > 1 ? argv[1] : ""); -} diff --git a/metadata-generator/tests/swift/TestMain.cpp b/metadata-generator/tests/swift/TestMain.cpp new file mode 100644 index 000000000..703df7888 --- /dev/null +++ b/metadata-generator/tests/swift/TestMain.cpp @@ -0,0 +1,5 @@ +#include "TestHarness.h" + +int main(int argc, char** argv) { + return TestHarness::runAll(argc > 1 ? argv[1] : ""); +} diff --git a/metadata-generator/tests/swift/TestSupport.h b/metadata-generator/tests/swift/TestSupport.h new file mode 100644 index 000000000..ee37a22db --- /dev/null +++ b/metadata-generator/tests/swift/TestSupport.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Swift/SymbolGraphLoader.h" +#include "TestHarness.h" + +namespace TestSupport { + +using namespace Swift; + +inline const ModuleSet& fixture() { + static ModuleSet set = loadSymbolGraphDirectory(SWIFT_FIXTURE_GRAPHS_DIR); + return set; +} + +inline const Module& demo() { + static const Module empty; + auto it = fixture().modules.find("SwiftDemo"); + return it == fixture().modules.end() ? empty : it->second; +} + +inline std::vector symbolsAt(const Module& module, + const std::string& path) { + std::vector result; + for (const auto& entry : module.symbols) { + if (llvm::join(entry.second.pathComponents, ".") == path) { + result.push_back(&entry.second); + } + } + return result; +} + +inline const Symbol* symbolAt(const Module& module, const std::string& path) { + auto symbols = symbolsAt(module, path); + return symbols.size() == 1 ? symbols.front() : nullptr; +} + +inline std::vector memberNames(const Module& module, + const Symbol& symbol) { + std::vector names; + for (const auto& id : symbol.memberIds) { + if (const Symbol* member = module.find(id)) { + names.push_back(member->name); + } + } + return names; +} + +inline bool contains(const std::vector& values, + const std::string& value) { + return std::find(values.begin(), values.end(), value) != values.end(); +} + +inline std::string diagnosticCodes(const std::vector& diagnostics) { + std::vector codes; + for (const auto& diagnostic : diagnostics) { + codes.push_back(diagnostic.code + "(" + diagnostic.message + ")"); + } + return llvm::join(codes, ", "); +} + +// Compares `actual` against a checked-in snapshot. NS_UPDATE_SNAPSHOTS=1 +// rewrites the snapshot instead. +inline void checkSnapshot(const std::string& fileName, + const std::string& actual) { + llvm::SmallString<256> snapshotPath(SWIFT_SNAPSHOT_DIR); + llvm::sys::path::append(snapshotPath, fileName); + + if (const char* update = std::getenv("NS_UPDATE_SNAPSHOTS"); + update && *update == '1') { + std::error_code error; + llvm::raw_fd_ostream out(snapshotPath, error, llvm::sys::fs::OF_Text); + REQUIRE(!error); + out << actual; + return; + } + + auto expected = llvm::MemoryBuffer::getFile(snapshotPath, /*IsText*/ true); + if (!expected) { + TestHarness::fail(__FILE__, __LINE__, + "missing snapshot " + snapshotPath.str().str() + + " (run with NS_UPDATE_SNAPSHOTS=1)"); + return; + } + if ((*expected)->getBuffer() != actual) { + llvm::SmallString<256> actualPath(snapshotPath); + actualPath += ".actual"; + std::error_code error; + llvm::raw_fd_ostream out(actualPath, error, llvm::sys::fs::OF_Text); + out << actual; + TestHarness::fail(__FILE__, __LINE__, + "snapshot mismatch: diff " + snapshotPath.str().str() + + " " + actualPath.str().str()); + } +} + +} // namespace TestSupport diff --git a/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json b/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json new file mode 100644 index 000000000..1b8aaa47d --- /dev/null +++ b/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json @@ -0,0 +1,1022 @@ +{ + "module": "SwiftDemo", + "totals": { + "declarations": { + "total": 95, + "objc-direct": 0, + "swift-generated": 52, + "swift-specialized": 5, + "type-only": 6, + "unsupported": 32, + "not-applicable": 0 + }, + "callable": { + "total": 80, + "objc-direct": 0, + "swift-generated": 43, + "swift-specialized": 5, + "type-only": 3, + "unsupported": 29, + "not-applicable": 0 + }, + "effectiveCallable": 43, + "compilerVerified": false, + "compiledThunks": null, + "runtimeTested": null + }, + "byKind": { + "actor": { + "total": 1, + "objc-direct": 0, + "swift-generated": 1, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 0, + "not-applicable": 0 + }, + "class": { + "total": 5, + "objc-direct": 0, + "swift-generated": 5, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 0, + "not-applicable": 0 + }, + "enum": { + "total": 3, + "objc-direct": 0, + "swift-generated": 1, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 2, + "not-applicable": 0 + }, + "enumCase": { + "total": 8, + "objc-direct": 0, + "swift-generated": 2, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 6, + "not-applicable": 0 + }, + "function": { + "total": 1, + "objc-direct": 0, + "swift-generated": 1, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 0, + "not-applicable": 0 + }, + "initializer": { + "total": 11, + "objc-direct": 0, + "swift-generated": 9, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 2, + "not-applicable": 0 + }, + "instanceMethod": { + "total": 31, + "objc-direct": 0, + "swift-generated": 12, + "swift-specialized": 5, + "type-only": 1, + "unsupported": 13, + "not-applicable": 0 + }, + "instanceProperty": { + "total": 18, + "objc-direct": 0, + "swift-generated": 12, + "swift-specialized": 0, + "type-only": 1, + "unsupported": 5, + "not-applicable": 0 + }, + "instanceSubscript": { + "total": 1, + "objc-direct": 0, + "swift-generated": 0, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 1, + "not-applicable": 0 + }, + "operator": { + "total": 2, + "objc-direct": 0, + "swift-generated": 0, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 2, + "not-applicable": 0 + }, + "protocol": { + "total": 2, + "objc-direct": 0, + "swift-generated": 0, + "swift-specialized": 0, + "type-only": 2, + "unsupported": 0, + "not-applicable": 0 + }, + "struct": { + "total": 3, + "objc-direct": 0, + "swift-generated": 2, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 1, + "not-applicable": 0 + }, + "typeAlias": { + "total": 1, + "objc-direct": 0, + "swift-generated": 0, + "swift-specialized": 0, + "type-only": 1, + "unsupported": 0, + "not-applicable": 0 + }, + "typeMethod": { + "total": 2, + "objc-direct": 0, + "swift-generated": 2, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 0, + "not-applicable": 0 + }, + "typeProperty": { + "total": 4, + "objc-direct": 0, + "swift-generated": 3, + "swift-specialized": 0, + "type-only": 1, + "unsupported": 0, + "not-applicable": 0 + }, + "variable": { + "total": 2, + "objc-direct": 0, + "swift-generated": 2, + "swift-specialized": 0, + "type-only": 0, + "unsupported": 0, + "not-applicable": 0 + } + }, + "reasons": { + "actor-isolated": 2, + "async": 2, + "closure": 4, + "collection": 1, + "enum-associated-values": 2, + "external-type-extension": 2, + "generic": 5, + "inout-parameter": 2, + "main-actor": 2, + "nested-type": 1, + "operator": 2, + "owner-not-bridged": 10, + "subscript": 1, + "unbridged-type": 3 + }, + "symbols": [ + { + "id": "s:9SwiftDemo0B0C", + "path": "Demo", + "kind": "class", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Demo.swift:5" + }, + { + "id": "s:9SwiftDemo0B0C5greet4name5timesS2S_SitF", + "path": "Demo.greet(name:times:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "greet", + "location": "file://Sources/SwiftDemo/Extensions.swift:2" + }, + { + "id": "s:9SwiftDemo0B0C5greet4nameS2S_tF", + "path": "Demo.greet(name:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "greet", + "location": "file://Sources/SwiftDemo/Demo.swift:7" + }, + { + "id": "s:9SwiftDemo0B0C7versionSSvpZ", + "path": "Demo.version", + "kind": "typeProperty", + "tier": "swift-generated", + "jsName": "version", + "location": "file://Sources/SwiftDemo/Extensions.swift:6" + }, + { + "id": "s:9SwiftDemo0B0CACycfc", + "path": "Demo.init()", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Demo.swift:6" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO", + "path": "ShapeError", + "kind": "enum", + "tier": "unsupported", + "reasons": [ + "enum-associated-values" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:50" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF", + "path": "ShapeError.invalidSide(_:)", + "kind": "enumCase", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:51" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF", + "path": "ShapeError.tooManySides(count:limit:)", + "kind": "enumCase", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:52" + }, + { + "id": "s:9SwiftDemo10ShapeErrorO7unknownyA2CmF", + "path": "ShapeError.unknown", + "kind": "enumCase", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:53" + }, + { + "id": "s:9SwiftDemo11Coordinatesa", + "path": "Coordinates", + "kind": "typeAlias", + "tier": "type-only", + "reasons": [ + "type-alias" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:137" + }, + { + "id": "s:9SwiftDemo11MeasurementO", + "path": "Measurement", + "kind": "enum", + "tier": "unsupported", + "reasons": [ + "enum-associated-values" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:56" + }, + { + "id": "s:9SwiftDemo11MeasurementO4UnitV", + "path": "Measurement.Unit", + "kind": "struct", + "tier": "unsupported", + "reasons": [ + "nested-type" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:61" + }, + { + "id": "s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc", + "path": "Measurement.Unit.init(symbol:)", + "kind": "initializer", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:63" + }, + { + "id": "s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp", + "path": "Measurement.Unit.symbol", + "kind": "instanceProperty", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:62" + }, + { + "id": "s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF", + "path": "Measurement.area(width:height:)", + "kind": "enumCase", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:58" + }, + { + "id": "s:9SwiftDemo11MeasurementO4noneyA2CmF", + "path": "Measurement.none", + "kind": "enumCase", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:59" + }, + { + "id": "s:9SwiftDemo11MeasurementO6isNoneSbvp", + "path": "Measurement.isNone", + "kind": "instanceProperty", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:66" + }, + { + "id": "s:9SwiftDemo11MeasurementO6lengthyACSdcACmF", + "path": "Measurement.length(_:)", + "kind": "enumCase", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:57" + }, + { + "id": "s:9SwiftDemo13defaultFlavorAA0D0Ovp", + "path": "defaultFlavor", + "kind": "variable", + "tier": "swift-generated", + "jsName": "defaultFlavor", + "location": "file://Sources/SwiftDemo/Shapes.swift:135" + }, + { + "id": "s:9SwiftDemo13globalCounterSivp", + "path": "globalCounter", + "kind": "variable", + "tier": "swift-generated", + "jsName": "globalCounter", + "location": "file://Sources/SwiftDemo/Shapes.swift:136" + }, + { + "id": "s:9SwiftDemo16makeDefaultPointAA0E0VyF", + "path": "makeDefaultPoint()", + "kind": "function", + "tier": "swift-generated", + "jsName": "makeDefaultPoint", + "location": "file://Sources/SwiftDemo/Shapes.swift:134" + }, + { + "id": "s:9SwiftDemo4RingV", + "path": "Ring", + "kind": "struct", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:72" + }, + { + "id": "s:9SwiftDemo4RingV1poiyA2C_ACtFZ", + "path": "Ring.+(_:_:)", + "kind": "operator", + "tier": "unsupported", + "reasons": [ + "operator" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:86" + }, + { + "id": "s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc", + "path": "Ring.init(inner:outer:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Shapes.swift:76" + }, + { + "id": "s:9SwiftDemo4RingV5innerAA5PointVvp", + "path": "Ring.inner", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "inner", + "location": "file://Sources/SwiftDemo/Shapes.swift:73" + }, + { + "id": "s:9SwiftDemo4RingV5outerAA5PointVvp", + "path": "Ring.outer", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "outer", + "location": "file://Sources/SwiftDemo/Shapes.swift:74" + }, + { + "id": "s:9SwiftDemo4RingV6expand2byySd_tF", + "path": "Ring.expand(by:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "expand", + "location": "file://Sources/SwiftDemo/Shapes.swift:81" + }, + { + "id": "s:9SwiftDemo5PointV", + "path": "Point", + "kind": "struct", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Demo.swift:10" + }, + { + "id": "s:9SwiftDemo5PointV11descriptionSSvp", + "path": "Point.description", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "description", + "location": "file://Sources/SwiftDemo/Extensions.swift:10" + }, + { + "id": "s:9SwiftDemo5PointV1x1yACSd_Sdtcfc", + "path": "Point.init(x:y:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Demo.swift:13" + }, + { + "id": "s:9SwiftDemo5PointV1xSdvp", + "path": "Point.x", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "x", + "location": "file://Sources/SwiftDemo/Demo.swift:11" + }, + { + "id": "s:9SwiftDemo5PointV1ySdvp", + "path": "Point.y", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "y", + "location": "file://Sources/SwiftDemo/Demo.swift:12" + }, + { + "id": "s:9SwiftDemo5PointV6lengthSdvp", + "path": "Point.length", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "length", + "location": "file://Sources/SwiftDemo/Extensions.swift:11" + }, + { + "id": "s:9SwiftDemo5ShapeP", + "path": "Shape", + "kind": "protocol", + "tier": "type-only", + "reasons": [ + "protocol" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:3" + }, + { + "id": "s:9SwiftDemo5ShapeP4areaSdvp", + "path": "Shape.area", + "kind": "instanceProperty", + "tier": "type-only", + "reasons": [ + "protocol-requirement" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:4" + }, + { + "id": "s:9SwiftDemo5ShapeP5sidesSivpZ", + "path": "Shape.sides", + "kind": "typeProperty", + "tier": "type-only", + "reasons": [ + "protocol-requirement" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:5" + }, + { + "id": "s:9SwiftDemo6CanvasC", + "path": "Canvas", + "kind": "class", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:102" + }, + { + "id": "s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF", + "path": "Canvas.draw(_:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "main-actor" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:104" + }, + { + "id": "s:9SwiftDemo6CanvasCACycfc", + "path": "Canvas.init()", + "kind": "initializer", + "tier": "unsupported", + "reasons": [ + "main-actor" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:103" + }, + { + "id": "s:9SwiftDemo6FlavorO", + "path": "Flavor", + "kind": "enum", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Demo.swift:16" + }, + { + "id": "s:9SwiftDemo6FlavorO11descriptionSSvp", + "path": "Flavor.description", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "description", + "location": "file://Sources/SwiftDemo/Extensions.swift:15" + }, + { + "id": "s:9SwiftDemo6FlavorO7vanillayA2CmF", + "path": "Flavor.vanilla", + "kind": "enumCase", + "tier": "swift-generated", + "jsName": "vanilla", + "location": "file://Sources/SwiftDemo/Demo.swift:16" + }, + { + "id": "s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc", + "path": "Flavor.init(rawValue:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor" + }, + { + "id": "s:9SwiftDemo6FlavorO9chocolateyA2CmF", + "path": "Flavor.chocolate", + "kind": "enumCase", + "tier": "swift-generated", + "jsName": "chocolate", + "location": "file://Sources/SwiftDemo/Demo.swift:16" + }, + { + "id": "s:9SwiftDemo6LoaderC", + "path": "Loader", + "kind": "class", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:107" + }, + { + "id": "s:9SwiftDemo6LoaderC10modernOnlyyyF", + "path": "Loader.modernOnly()", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "modernOnly", + "location": "file://Sources/SwiftDemo/Shapes.swift:125" + }, + { + "id": "s:9SwiftDemo6LoaderC11legacyFetchyyF", + "path": "Loader.legacyFetch()", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "legacyFetch", + "location": "file://Sources/SwiftDemo/Shapes.swift:128" + }, + { + "id": "s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF", + "path": "Loader.withCompletion(_:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "closure" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:117" + }, + { + "id": "s:9SwiftDemo6LoaderC4eachyyySiXEF", + "path": "Loader.each(_:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "closure" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:118" + }, + { + "id": "s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF", + "path": "Loader.load(path:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "unbridged-type:Foundation.Data" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:110" + }, + { + "id": "s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF", + "path": "Loader.wait(seconds:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "async" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:112" + }, + { + "id": "s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF", + "path": "Loader.fetch(url:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "async" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:111" + }, + { + "id": "s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF", + "path": "Loader.first(of:)", + "kind": "instanceMethod", + "tier": "swift-specialized", + "reasons": [ + "generic" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:115" + }, + { + "id": "s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF", + "path": "Loader.lookup(table:key:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "collection" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:120" + }, + { + "id": "s:9SwiftDemo6LoaderC6updateyyAA5PointVzF", + "path": "Loader.update(_:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "inout-parameter" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:122" + }, + { + "id": "s:9SwiftDemo6LoaderC8oldFetchyyF", + "path": "Loader.oldFetch()", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "oldFetch", + "location": "file://Sources/SwiftDemo/Shapes.swift:131" + }, + { + "id": "s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF", + "path": "Loader.transform(_:)", + "kind": "instanceMethod", + "tier": "swift-specialized", + "reasons": [ + "generic" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:114" + }, + { + "id": "s:9SwiftDemo6LoaderCACycfc", + "path": "Loader.init()", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Shapes.swift:108" + }, + { + "id": "s:9SwiftDemo6SquareC", + "path": "Square", + "kind": "class", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:35" + }, + { + "id": "s:9SwiftDemo6SquareC4areaSdvp", + "path": "Square.area", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "area", + "location": "file://Sources/SwiftDemo/Shapes.swift:43" + }, + { + "id": "s:9SwiftDemo6SquareC4sideACSd_tcfc", + "path": "Square.init(side:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Shapes.swift:38" + }, + { + "id": "s:9SwiftDemo6SquareC4sideSdvp", + "path": "Square.side", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "side", + "location": "file://Sources/SwiftDemo/Shapes.swift:36" + }, + { + "id": "s:9SwiftDemo6SquareC5greet4nameS2S_tF", + "path": "Square.greet(name:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "greet", + "location": "file://Sources/SwiftDemo/Shapes.swift:45" + }, + { + "id": "s:9SwiftDemo6SquareC5scale2byySd_tF", + "path": "Square.scale(by:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "scale", + "location": "file://Sources/SwiftDemo/Shapes.swift:47" + }, + { + "id": "s:9SwiftDemo6SquareC5sidesSivpZ", + "path": "Square.sides", + "kind": "typeProperty", + "tier": "swift-generated", + "jsName": "sides", + "location": "file://Sources/SwiftDemo/Shapes.swift:44" + }, + { + "id": "s:9SwiftDemo7CounterC", + "path": "Counter", + "kind": "actor", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:91" + }, + { + "id": "s:9SwiftDemo7CounterC5labelSSyF", + "path": "Counter.label()", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "label", + "location": "file://Sources/SwiftDemo/Shapes.swift:98" + }, + { + "id": "s:9SwiftDemo7CounterC5valueSivp", + "path": "Counter.value", + "kind": "instanceProperty", + "tier": "unsupported", + "reasons": [ + "actor-isolated" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:92" + }, + { + "id": "s:9SwiftDemo7CounterC9incrementSiyF", + "path": "Counter.increment()", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "actor-isolated" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:94" + }, + { + "id": "s:9SwiftDemo7CounterCACycfc", + "path": "Counter.init()", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Shapes.swift:93" + }, + { + "id": "s:9SwiftDemo7GreeterP", + "path": "Greeter", + "kind": "protocol", + "tier": "type-only", + "reasons": [ + "protocol" + ], + "location": "file://Sources/SwiftDemo/Demo.swift:1" + }, + { + "id": "s:9SwiftDemo7GreeterP5greet4nameS2S_tF", + "path": "Greeter.greet(name:)", + "kind": "instanceMethod", + "tier": "type-only", + "reasons": [ + "protocol-requirement" + ], + "location": "file://Sources/SwiftDemo/Demo.swift:2" + }, + { + "id": "s:9SwiftDemo7PolygonC", + "path": "Polygon", + "kind": "class", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:8" + }, + { + "id": "s:9SwiftDemo7PolygonC11vertexCountSivp", + "path": "Polygon.vertexCount", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "vertexCount", + "location": "file://Sources/SwiftDemo/Shapes.swift:10" + }, + { + "id": "s:9SwiftDemo7PolygonC4makeACyFZ", + "path": "Polygon.make()", + "kind": "typeMethod", + "tier": "swift-generated", + "jsName": "make", + "location": "file://Sources/SwiftDemo/Shapes.swift:27" + }, + { + "id": "s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc", + "path": "Polygon.init(name:vertexCount:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Shapes.swift:13" + }, + { + "id": "s:9SwiftDemo7PolygonC4nameACSgSS_tcfc", + "path": "Polygon.init(name:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Shapes.swift:18" + }, + { + "id": "s:9SwiftDemo7PolygonC4nameSSvp", + "path": "Polygon.name", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "name", + "location": "file://Sources/SwiftDemo/Shapes.swift:9" + }, + { + "id": "s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF", + "path": "Polygon.scale(x:y:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "scale", + "location": "file://Sources/SwiftDemo/Shapes.swift:25" + }, + { + "id": "s:9SwiftDemo7PolygonC5scale2byySd_tF", + "path": "Polygon.scale(by:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "scale", + "ambiguousOverload": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:23" + }, + { + "id": "s:9SwiftDemo7PolygonC5scale2byySi_tF", + "path": "Polygon.scale(by:)", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "scale", + "ambiguousOverload": true, + "location": "file://Sources/SwiftDemo/Shapes.swift:24" + }, + { + "id": "s:9SwiftDemo7PolygonC6sharedACvpZ", + "path": "Polygon.shared", + "kind": "typeProperty", + "tier": "swift-generated", + "jsName": "shared", + "location": "file://Sources/SwiftDemo/Shapes.swift:11" + }, + { + "id": "s:9SwiftDemo7PolygonC8describeySSACSgFZ", + "path": "Polygon.describe(_:)", + "kind": "typeMethod", + "tier": "swift-generated", + "jsName": "describe", + "location": "file://Sources/SwiftDemo/Shapes.swift:28" + }, + { + "id": "s:9SwiftDemo7PolygonCyAA5PointVSicip", + "path": "Polygon.subscript(_:)", + "kind": "instanceSubscript", + "tier": "unsupported", + "reasons": [ + "subscript" + ], + "location": "file://Sources/SwiftDemo/Shapes.swift:30" + }, + { + "id": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "path": "Flavor.!=(_:_:)", + "kind": "operator", + "tier": "unsupported", + "reasons": [ + "operator" + ] + }, + { + "id": "s:SS9SwiftDemoE7shoutedSSvp", + "path": "String.shouted", + "kind": "instanceProperty", + "tier": "unsupported", + "reasons": [ + "external-type-extension" + ], + "location": "file://Sources/SwiftDemo/Extensions.swift:19" + }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "path": "Flavor.hashValue", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "hashValue" + }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO", + "path": "Flavor.hash(into:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "inout-parameter" + ] + }, + { + "id": "s:Sa9SwiftDemoAA5PointVRszlE8centroidACyF", + "path": "Array.centroid()", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "external-type-extension" + ], + "location": "file://Sources/SwiftDemo/Extensions.swift:23" + }, + { + "id": "s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "path": "Counter.assertIsolated(_:file:line:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "closure", + "unbridged-type:Swift.StaticString" + ] + }, + { + "id": "s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "path": "Counter.assumeIsolated(_:file:line:)", + "kind": "instanceMethod", + "tier": "swift-specialized", + "reasons": [ + "generic" + ] + }, + { + "id": "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "path": "Counter.withSerialExecutor(_:)", + "kind": "instanceMethod", + "tier": "swift-specialized", + "reasons": [ + "generic" + ] + }, + { + "id": "s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "path": "Counter.withSerialExecutor(_:)", + "kind": "instanceMethod", + "tier": "swift-specialized", + "reasons": [ + "generic" + ] + }, + { + "id": "s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC", + "path": "Counter.preconditionIsolated(_:file:line:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "closure", + "unbridged-type:Swift.StaticString" + ] + }, + { + "id": "s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO", + "path": "ShapeError.localizedDescription", + "kind": "instanceProperty", + "tier": "unsupported", + "reasons": [ + "owner-not-bridged" + ] + } + ] +} diff --git a/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift b/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift new file mode 100644 index 000000000..c714e7153 --- /dev/null +++ b/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift @@ -0,0 +1,254 @@ +// Generated by objc-metadata-generator. Compiler-validation probes for +// the Swift-generated surface of module SwiftDemo. +import Foundation +import SwiftDemo + +// s:9SwiftDemo0B0C +func __nsProbe0(_ value: SwiftDemo.Demo) -> SwiftDemo.Demo { value } + +// s:9SwiftDemo0B0C5greet4name5timesS2S_SitF +func __nsProbe1(_ receiver: SwiftDemo.Demo, _ a0: String, _ a1: Int) { + let _: String = receiver.`greet`(name: a0, times: a1) +} + +// s:9SwiftDemo0B0C5greet4nameS2S_tF +func __nsProbe2(_ receiver: SwiftDemo.Demo, _ a0: String) { + let _: String = receiver.`greet`(name: a0) +} + +// s:9SwiftDemo0B0C7versionSSvpZ +func __nsProbe3() { + let _: String = SwiftDemo.Demo.`version` +} + +// s:9SwiftDemo0B0CACycfc +func __nsProbe4() { + let _: SwiftDemo.Demo = SwiftDemo.Demo() +} + +// s:9SwiftDemo13defaultFlavorAA0D0Ovp +func __nsProbe5() { + let _: SwiftDemo.Flavor = SwiftDemo.`defaultFlavor` +} + +// s:9SwiftDemo13globalCounterSivp +func __nsProbe6(_ newValue: Int) { + let _: Int = SwiftDemo.`globalCounter` + SwiftDemo.`globalCounter` = newValue +} + +// s:9SwiftDemo16makeDefaultPointAA0E0VyF +func __nsProbe7() { + let _: SwiftDemo.Point = SwiftDemo.`makeDefaultPoint`() +} + +// s:9SwiftDemo4RingV +func __nsProbe8(_ value: SwiftDemo.Ring) -> SwiftDemo.Ring { value } + +// s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc +func __nsProbe9(_ a0: SwiftDemo.Point, _ a1: SwiftDemo.Point) { + let _: SwiftDemo.Ring = SwiftDemo.Ring(inner: a0, outer: a1) +} + +// s:9SwiftDemo4RingV5innerAA5PointVvp +func __nsProbe10(_ receiver: inout SwiftDemo.Ring, _ newValue: SwiftDemo.Point) { + let _: SwiftDemo.Point = receiver.`inner` + receiver.`inner` = newValue +} + +// s:9SwiftDemo4RingV5outerAA5PointVvp +func __nsProbe11(_ receiver: inout SwiftDemo.Ring, _ newValue: SwiftDemo.Point) { + let _: SwiftDemo.Point = receiver.`outer` + receiver.`outer` = newValue +} + +// s:9SwiftDemo4RingV6expand2byySd_tF +func __nsProbe12(_ receiver: inout SwiftDemo.Ring, _ a0: Double) { + let _: Void = receiver.`expand`(by: a0) +} + +// s:9SwiftDemo5PointV +func __nsProbe13(_ value: SwiftDemo.Point) -> SwiftDemo.Point { value } + +// s:9SwiftDemo5PointV11descriptionSSvp +func __nsProbe14(_ receiver: SwiftDemo.Point) { + let _: String = receiver.`description` +} + +// s:9SwiftDemo5PointV1x1yACSd_Sdtcfc +func __nsProbe15(_ a0: Double, _ a1: Double) { + let _: SwiftDemo.Point = SwiftDemo.Point(x: a0, y: a1) +} + +// s:9SwiftDemo5PointV1xSdvp +func __nsProbe16(_ receiver: inout SwiftDemo.Point, _ newValue: Double) { + let _: Double = receiver.`x` + receiver.`x` = newValue +} + +// s:9SwiftDemo5PointV1ySdvp +func __nsProbe17(_ receiver: inout SwiftDemo.Point, _ newValue: Double) { + let _: Double = receiver.`y` + receiver.`y` = newValue +} + +// s:9SwiftDemo5PointV6lengthSdvp +func __nsProbe18(_ receiver: SwiftDemo.Point) { + let _: Double = receiver.`length` +} + +// s:9SwiftDemo6CanvasC +func __nsProbe19(_ value: SwiftDemo.Canvas) -> SwiftDemo.Canvas { value } + +// s:9SwiftDemo6FlavorO +func __nsProbe20(_ value: SwiftDemo.Flavor) -> SwiftDemo.Flavor { value } + +// s:9SwiftDemo6FlavorO11descriptionSSvp +func __nsProbe21(_ receiver: SwiftDemo.Flavor) { + let _: String = receiver.`description` +} + +// s:9SwiftDemo6FlavorO7vanillayA2CmF +func __nsProbe22() { + let _: SwiftDemo.Flavor = SwiftDemo.Flavor.`vanilla` +} + +// s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc +func __nsProbe23(_ a0: Int) { + let _: SwiftDemo.Flavor? = SwiftDemo.Flavor(rawValue: a0) +} + +// s:9SwiftDemo6FlavorO9chocolateyA2CmF +func __nsProbe24() { + let _: SwiftDemo.Flavor = SwiftDemo.Flavor.`chocolate` +} + +// s:9SwiftDemo6LoaderC +func __nsProbe25(_ value: SwiftDemo.Loader) -> SwiftDemo.Loader { value } + +// s:9SwiftDemo6LoaderC10modernOnlyyyF +@available(iOS 16.0, *) +func __nsProbe26(_ receiver: SwiftDemo.Loader) { + let _: Void = receiver.`modernOnly`() +} + +// s:9SwiftDemo6LoaderC11legacyFetchyyF +func __nsProbe27(_ receiver: SwiftDemo.Loader) { + let _: Void = receiver.`legacyFetch`() +} + +// s:9SwiftDemo6LoaderC8oldFetchyyF +func __nsProbe28(_ receiver: SwiftDemo.Loader) { + let _: Void = receiver.`oldFetch`() +} + +// s:9SwiftDemo6LoaderCACycfc +func __nsProbe29() { + let _: SwiftDemo.Loader = SwiftDemo.Loader() +} + +// s:9SwiftDemo6SquareC +func __nsProbe30(_ value: SwiftDemo.Square) -> SwiftDemo.Square { value } + +// s:9SwiftDemo6SquareC4areaSdvp +func __nsProbe31(_ receiver: SwiftDemo.Square) { + let _: Double = receiver.`area` +} + +// s:9SwiftDemo6SquareC4sideACSd_tcfc +func __nsProbe32(_ a0: Double) { + let _: SwiftDemo.Square = SwiftDemo.Square(side: a0) +} + +// s:9SwiftDemo6SquareC4sideSdvp +func __nsProbe33(_ receiver: SwiftDemo.Square, _ newValue: Double) { + let _: Double = receiver.`side` + receiver.`side` = newValue +} + +// s:9SwiftDemo6SquareC5greet4nameS2S_tF +func __nsProbe34(_ receiver: SwiftDemo.Square, _ a0: String) { + let _: String = receiver.`greet`(name: a0) +} + +// s:9SwiftDemo6SquareC5scale2byySd_tF +func __nsProbe35(_ receiver: SwiftDemo.Square, _ a0: Double) { + let _: Void = receiver.`scale`(by: a0) +} + +// s:9SwiftDemo6SquareC5sidesSivpZ +func __nsProbe36() { + let _: Int = SwiftDemo.Square.`sides` +} + +// s:9SwiftDemo7CounterC +func __nsProbe37(_ value: SwiftDemo.Counter) -> SwiftDemo.Counter { value } + +// s:9SwiftDemo7CounterC5labelSSyF +func __nsProbe38(_ receiver: SwiftDemo.Counter) { + let _: String = receiver.`label`() +} + +// s:9SwiftDemo7CounterCACycfc +func __nsProbe39() { + let _: SwiftDemo.Counter = SwiftDemo.Counter() +} + +// s:9SwiftDemo7PolygonC +func __nsProbe40(_ value: SwiftDemo.Polygon) -> SwiftDemo.Polygon { value } + +// s:9SwiftDemo7PolygonC11vertexCountSivp +func __nsProbe41(_ receiver: SwiftDemo.Polygon) { + let _: Int = receiver.`vertexCount` +} + +// s:9SwiftDemo7PolygonC4makeACyFZ +func __nsProbe42() { + let _: SwiftDemo.Polygon = SwiftDemo.Polygon.`make`() +} + +// s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc +func __nsProbe43(_ a0: String, _ a1: Int) { + let _: SwiftDemo.Polygon = SwiftDemo.Polygon(name: a0, vertexCount: a1) +} + +// s:9SwiftDemo7PolygonC4nameACSgSS_tcfc +func __nsProbe44(_ a0: String) { + let _: SwiftDemo.Polygon? = SwiftDemo.Polygon(name: a0) +} + +// s:9SwiftDemo7PolygonC4nameSSvp +func __nsProbe45(_ receiver: SwiftDemo.Polygon) { + let _: String = receiver.`name` +} + +// s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF +func __nsProbe46(_ receiver: SwiftDemo.Polygon, _ a0: Double, _ a1: Double) { + let _: Void = receiver.`scale`(x: a0, y: a1) +} + +// s:9SwiftDemo7PolygonC5scale2byySd_tF +func __nsProbe47(_ receiver: SwiftDemo.Polygon, _ a0: Double) { + let _: Void = receiver.`scale`(by: a0) +} + +// s:9SwiftDemo7PolygonC5scale2byySi_tF +func __nsProbe48(_ receiver: SwiftDemo.Polygon, _ a0: Int) { + let _: Void = receiver.`scale`(by: a0) +} + +// s:9SwiftDemo7PolygonC6sharedACvpZ +func __nsProbe49() { + let _: SwiftDemo.Polygon = SwiftDemo.Polygon.`shared` +} + +// s:9SwiftDemo7PolygonC8describeySSACSgFZ +func __nsProbe50(_ a0: SwiftDemo.Polygon?) { + let _: String = SwiftDemo.Polygon.`describe`(a0) +} + +// s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO +func __nsProbe51(_ receiver: SwiftDemo.Flavor) { + let _: Int = receiver.`hashValue` +} + From 22f8e56eb57540fab2515aa466380f89181c61dd Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 20 Oct 2026 11:47:01 -0700 Subject: [PATCH 5/5] feat(metadata-generator): Swift interop thunks and TypeScript declarations PR 3-5 of the Swift interop plan, generator side: emit the Swift code the runtime calls, and declare exactly that surface to TypeScript. - SwiftSurface is the registration model (type table, member kinds, flags and signature codes of NativeScript/runtime/SwiftInterop.h) shared by the thunk emitter and the TypeScript writer, so the two cannot disagree. - ThunkEmitter (--swift-thunk-output) writes +NativeScript.swift: one thunk per generated callable, reading 24-byte argument slots and reporting through the runtime's API table without importing runtime headers, plus ns_swift_register_ (@c when the compiler has it, @_cdecl otherwise). Classes and actors cross as retained handles with their dynamic type index, structs as boxes the JS object owns, payload- less enums as case names; availability is checked at call time. Enum cases are qualified so a case named `none` is not Optional.none. - SwiftDefinitionWriter now writes swift!.d.ts as `declare module "ns:swift/"`, mirroring the runtime's member groups, inherited overloads, signature keys and ambiguity rules, and augments ns:swift's SwiftModules interface. - The SwiftDemo fixture gains value, error and lifetime declarations, a checked-in Interop/ copy of its generated thunks (kept identical to the generator's output by a test) and a two-module Package.swift. - Tests type-check the thunks against the separately compiled fixture module and the declarations with tsc when available. All thunks generated for SwiftUI, Foundation, Charts, SwiftData, RegexBuilder, WeatherKit and Observation (about 1,860) type-check against the iOS 18 simulator SDK. --- metadata-generator/README.md | 18 +- .../Interop/SwiftDemo+NativeScript.swift | 712 ++++++++++++++++++ .../TestFixtures/SwiftDemo/Package.swift | 10 +- .../TestFixtures/SwiftDemo/README.md | 8 +- .../SwiftDemo/Sources/SwiftDemo/Shapes.swift | 5 + .../SwiftDemo/Sources/SwiftDemo/Values.swift | 26 + .../symbolgraphs/SwiftDemo.symbols.json | 2 +- metadata-generator/src/CMakeLists.txt | 4 + metadata-generator/src/Swift/SwiftSurface.cpp | 163 ++++ metadata-generator/src/Swift/SwiftSurface.h | 78 ++ metadata-generator/src/Swift/ThunkEmitter.cpp | 609 +++++++++++++++ metadata-generator/src/Swift/ThunkEmitter.h | 29 + .../src/TypeScript/SwiftDefinitionWriter.cpp | 596 ++++++++++++++- .../src/TypeScript/SwiftDefinitionWriter.h | 14 +- metadata-generator/src/main.cpp | 32 +- metadata-generator/tests/CMakeLists.txt | 5 + .../tests/swift/ClassifierTests.cpp | 106 +-- .../tests/swift/SwiftToolchain.h | 105 +++ .../tests/swift/SymbolGraphLoaderTests.cpp | 22 +- metadata-generator/tests/swift/TestSupport.h | 34 +- .../tests/swift/ThunkEmitterTests.cpp | 133 ++++ .../swift/snapshots/SwiftDemo.coverage.json | 286 +++++-- .../tests/swift/snapshots/SwiftDemo.ir.json | 539 +++++++++++-- .../swift/snapshots/SwiftDemo.probe.swift | 170 +++-- .../swift/snapshots/swift!SwiftDemo.d.ts | 141 +++- .../tests/swift/typescript/usage.ts | 30 + 26 files changed, 3538 insertions(+), 339 deletions(-) create mode 100644 metadata-generator/TestFixtures/SwiftDemo/Interop/SwiftDemo+NativeScript.swift create mode 100644 metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Values.swift create mode 100644 metadata-generator/src/Swift/SwiftSurface.cpp create mode 100644 metadata-generator/src/Swift/SwiftSurface.h create mode 100644 metadata-generator/src/Swift/ThunkEmitter.cpp create mode 100644 metadata-generator/src/Swift/ThunkEmitter.h create mode 100644 metadata-generator/tests/swift/SwiftToolchain.h create mode 100644 metadata-generator/tests/swift/ThunkEmitterTests.cpp create mode 100644 metadata-generator/tests/swift/typescript/usage.ts diff --git a/metadata-generator/README.md b/metadata-generator/README.md index b94dbd301..b0ee3f57a 100644 --- a/metadata-generator/README.md +++ b/metadata-generator/README.md @@ -60,9 +60,13 @@ diagnostics with stable codes (`invalid-json`, `unsupported-format-version`, `duplicate-symbol`, `parameter-label-mismatch`, ...); errors make the generator exit non-zero. -Swift declarations are not callable from JavaScript yet, so the emitted -`swift!.d.ts` is type-only: it names the module's top-level types and -declares no members. +`--swift-thunk-output ` writes `+NativeScript.swift`: a Swift +thunk for every declaration the runtime can call, plus the +`ns_swift_register_` function the runtime looks up. `-output-typescript` +writes `swift!.d.ts`, declaring exactly that surface as the +`ns:swift/` module. Both come from the same registration model +(`src/Swift/SwiftSurface.h`). See `docs/swift-interop.md` for the app-side +workflow and the JavaScript semantics. ### Capability classification and coverage @@ -142,8 +146,12 @@ cmake --build build --target swift-symbolgraph-tests ``` The snapshot tests (`IRSnapshot`, `TypeScriptSnapshot`, `CoverageSnapshot`, -`ProbeSnapshot`) compare against `tests/swift/snapshots/`. `ProbesTypeCheck` +`ProbeSnapshot`) compare against `tests/swift/snapshots/`; +`ThunkSourceMatchesFixtureInterop` keeps +`TestFixtures/SwiftDemo/Interop/SwiftDemo+NativeScript.swift`, which TestRunner +compiles, identical to the generator's output. `TypeScriptUsageCompiles` runs +`tsc` (from `PATH` or `NS_TSC`) over `tests/swift/typescript/usage.ts`. `ProbesTypeCheck` and the `Verifier*` tests build the fixture module and run the Swift compiler; they are skipped when `xcrun` is unavailable. After an intended output change, regenerate them with -`NS_UPDATE_SNAPSHOTS=1 ./build/bin/swift-symbolgraph-tests Snapshot` and review +`NS_UPDATE_SNAPSHOTS=1 ./build/bin/swift-symbolgraph-tests` and review the diff. diff --git a/metadata-generator/TestFixtures/SwiftDemo/Interop/SwiftDemo+NativeScript.swift b/metadata-generator/TestFixtures/SwiftDemo/Interop/SwiftDemo+NativeScript.swift new file mode 100644 index 000000000..6a94315e5 --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/Interop/SwiftDemo+NativeScript.swift @@ -0,0 +1,712 @@ +// Generated by objc-metadata-generator from the SwiftDemo symbol graphs. Do not edit. +// NativeScript Swift interop thunks, ABI 1: see NativeScript/runtime/SwiftInterop.h. +import Foundation +import SwiftDemo + +private typealias __NSThunk = @convention(c) (UnsafeMutableRawPointer, UnsafeRawPointer?, Int) -> Void +private typealias __NSRelease = @convention(c) (UnsafeMutableRawPointer) -> Void + +private final class __NSBox { + var value: Value + init(_ value: Value) { self.value = value } +} + +// Reads arguments (24-byte slots) and reports results through the runtime's +// API table, whose address is the first word of the call context. +private struct __NSCall { + let call: UnsafeMutableRawPointer + let args: UnsafeRawPointer? + + private func slot(_ index: Int, _: Function.Type) -> Function { + call.load(as: UnsafeRawPointer.self).load(fromByteOffset: index * 8, as: Function.self) + } + + func isNull(_ i: Int) -> Bool { args!.load(fromByteOffset: i * 24, as: UInt32.self) == 0 } + func bool(_ i: Int) -> Bool { args!.load(fromByteOffset: i * 24 + 8, as: UInt8.self) != 0 } + func int64(_ i: Int) -> Int64 { args!.load(fromByteOffset: i * 24 + 8, as: Int64.self) } + func uint64(_ i: Int) -> UInt64 { args!.load(fromByteOffset: i * 24 + 8, as: UInt64.self) } + func double(_ i: Int) -> Double { args!.load(fromByteOffset: i * 24 + 8, as: Double.self) } + func string(_ i: Int) -> String { + let base = args!.load(fromByteOffset: i * 24 + 8, as: UnsafePointer?.self) + let length = Int(args!.load(fromByteOffset: i * 24 + 16, as: UInt64.self)) + return String(decoding: UnsafeBufferPointer(start: base, count: length), as: UTF8.self) + } + func object(_ i: Int) -> AnyObject { + let pointer = args!.load(fromByteOffset: i * 24 + 8, as: UnsafeMutableRawPointer.self) + return Unmanaged.fromOpaque(pointer).takeUnretainedValue() + } + + func returnVoid() { + slot(0, (@convention(c) (UnsafeMutableRawPointer) -> Void).self)(call) + } + func returnBool(_ value: Bool) { + slot(1, (@convention(c) (UnsafeMutableRawPointer, UInt8) -> Void).self)(call, value ? 1 : 0) + } + func returnInt64(_ value: Int64) { + slot(2, (@convention(c) (UnsafeMutableRawPointer, Int64) -> Void).self)(call, value) + } + func returnUInt64(_ value: UInt64) { + slot(3, (@convention(c) (UnsafeMutableRawPointer, UInt64) -> Void).self)(call, value) + } + func returnDouble(_ value: Double) { + slot(4, (@convention(c) (UnsafeMutableRawPointer, Double) -> Void).self)(call, value) + } + func returnString(_ value: String) { + var value = value + value.withUTF8 { + slot(5, (@convention(c) (UnsafeMutableRawPointer, UnsafePointer?, Int) -> Void).self)( + call, $0.baseAddress, $0.count) + } + } + func returnNull() { + slot(6, (@convention(c) (UnsafeMutableRawPointer) -> Void).self)(call) + } + func returnObject(_ object: AnyObject, _ typeIndex: UInt32) { + slot(7, (@convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer, UInt32) -> Void).self)( + call, Unmanaged.passRetained(object).toOpaque(), typeIndex) + } + func throwError(_ error: any Error) { + report(String(describing: error), String(reflecting: type(of: error))) + } + func throwMessage(_ message: String) { + report(message, "") + } + func throwTypeError(_ message: String) { + var message = message + message.withUTF8 { + slot(9, (@convention(c) (UnsafeMutableRawPointer, UnsafePointer?, Int) -> Void).self)( + call, $0.baseAddress, $0.count) + } + } + private func report(_ message: String, _ type: String) { + var message = message + var type = type + message.withUTF8 { messageBytes in + type.withUTF8 { typeBytes in + slot(8, (@convention(c) (UnsafeMutableRawPointer, UnsafePointer?, Int, + UnsafePointer?, Int) -> Void).self)( + call, messageBytes.baseAddress, messageBytes.count, typeBytes.baseAddress, typeBytes.count) + } + } + } +} + +private func __nsRelease(_ object: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(object).release() +} + +private func __nsEnum1(_ name: String) -> SwiftDemo.Precipitation? { + switch name { + case "rain": return SwiftDemo.Precipitation.`rain` + case "snow": return SwiftDemo.Precipitation.`snow` + case "none": return SwiftDemo.Precipitation.`none` + default: return nil + } +} + +private func __nsEnumName1(_ value: SwiftDemo.Precipitation) -> String { + switch value { + case SwiftDemo.Precipitation.`rain`: return "rain" + case SwiftDemo.Precipitation.`snow`: return "snow" + case SwiftDemo.Precipitation.`none`: return "none" + @unknown default: return String(describing: value) + } +} + +private func __nsEnum5(_ name: String) -> SwiftDemo.Flavor? { + switch name { + case "vanilla": return SwiftDemo.Flavor.`vanilla` + case "chocolate": return SwiftDemo.Flavor.`chocolate` + default: return nil + } +} + +private func __nsEnumName5(_ value: SwiftDemo.Flavor) -> String { + switch value { + case SwiftDemo.Flavor.`vanilla`: return "vanilla" + case SwiftDemo.Flavor.`chocolate`: return "chocolate" + @unknown default: return String(describing: value) + } +} + +private func __nsTypeIndex(_ object: AnyObject, _ declared: UInt32) -> UInt32 { + if object is SwiftDemo.Square { return 7 } + return declared +} + +// s:9SwiftDemo0B0C5greet4name5timesS2S_SitF +private func __nsThunk0(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Demo else { return rt.throwTypeError("receiver must be SwiftDemo.Demo") } + let a0 = rt.string(1) + let a1 = Int(truncatingIfNeeded: rt.int64(2)) + let result: String = receiver.`greet`(name: a0, times: a1) + rt.returnString(result) +} + +// s:9SwiftDemo0B0C5greet4nameS2S_tF +private func __nsThunk1(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Demo else { return rt.throwTypeError("receiver must be SwiftDemo.Demo") } + let a0 = rt.string(1) + let result: String = receiver.`greet`(name: a0) + rt.returnString(result) +} + +// s:9SwiftDemo0B0C7versionSSvpZ +private func __nsThunk2(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: String = SwiftDemo.Demo.`version` + rt.returnString(result) +} + +// s:9SwiftDemo0B0CACycfc +private func __nsThunk3(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Demo = SwiftDemo.Demo() + rt.returnObject(result, __nsTypeIndex(result, 0)) +} + +// s:9SwiftDemo10echoUInt64ys0D0VADF +private func __nsThunk4(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.uint64(0) + let result: UInt64 = SwiftDemo.`echoUInt64`(a0) + rt.returnUInt64(UInt64(result)) +} + +// s:9SwiftDemo10largestIntSiyF +private func __nsThunk5(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: Int = SwiftDemo.`largestInt`() + rt.returnInt64(Int64(result)) +} + +// s:9SwiftDemo11checkedSideyS2dKF +private func __nsThunk6(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.double(0) + do { + let result: Double = try SwiftDemo.`checkedSide`(a0) + rt.returnDouble(Double(result)) + } catch { + rt.throwError(error) + } +} + +// s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc +private func __nsThunk7(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.string(0) + let result: SwiftDemo.Precipitation? = SwiftDemo.Precipitation(rawValue: a0) + if let result { + rt.returnString(__nsEnumName1(result)) + } else { + rt.returnNull() + } +} + +// s:9SwiftDemo13defaultFlavorAA0D0Ovp +private func __nsThunk8(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Flavor = SwiftDemo.`defaultFlavor` + rt.returnString(__nsEnumName5(result)) +} + +// s:9SwiftDemo13globalCounterSivp +private func __nsThunk9(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: Int = SwiftDemo.`globalCounter` + rt.returnInt64(Int64(result)) +} + +// s:9SwiftDemo13globalCounterSivp (setter) +private func __nsThunk10(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let newValue = Int(truncatingIfNeeded: rt.int64(0)) + SwiftDemo.`globalCounter` = newValue + rt.returnVoid() +} + +// s:9SwiftDemo16makeDefaultPointAA0E0VyF +private func __nsThunk11(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Point = SwiftDemo.`makeDefaultPoint`() + rt.returnObject(__NSBox(result), 3) +} + +// s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc +private func __nsThunk12(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let a0 = (rt.object(0) as? __NSBox)?.value else { return rt.throwTypeError("argument 1 must be SwiftDemo.Point") } + guard let a1 = (rt.object(1) as? __NSBox)?.value else { return rt.throwTypeError("argument 2 must be SwiftDemo.Point") } + let result: SwiftDemo.Ring = SwiftDemo.Ring(inner: a0, outer: a1) + rt.returnObject(__NSBox(result), 2) +} + +// s:9SwiftDemo4RingV5innerAA5PointVvp +private func __nsThunk13(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Ring") } + let result: SwiftDemo.Point = box.value.`inner` + rt.returnObject(__NSBox(result), 3) +} + +// s:9SwiftDemo4RingV5innerAA5PointVvp (setter) +private func __nsThunk14(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Ring") } + guard let newValue = (rt.object(1) as? __NSBox)?.value else { return rt.throwTypeError("value must be SwiftDemo.Point") } + box.value.`inner` = newValue + rt.returnVoid() +} + +// s:9SwiftDemo4RingV5outerAA5PointVvp +private func __nsThunk15(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Ring") } + let result: SwiftDemo.Point = box.value.`outer` + rt.returnObject(__NSBox(result), 3) +} + +// s:9SwiftDemo4RingV5outerAA5PointVvp (setter) +private func __nsThunk16(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Ring") } + guard let newValue = (rt.object(1) as? __NSBox)?.value else { return rt.throwTypeError("value must be SwiftDemo.Point") } + box.value.`outer` = newValue + rt.returnVoid() +} + +// s:9SwiftDemo4RingV6expand2byySd_tF +private func __nsThunk17(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Ring") } + let a0 = rt.double(1) + let _: Void = box.value.`expand`(by: a0) + rt.returnVoid() +} + +// s:9SwiftDemo5PointV11descriptionSSvp +private func __nsThunk18(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Point") } + let result: String = box.value.`description` + rt.returnString(result) +} + +// s:9SwiftDemo5PointV1x1yACSd_Sdtcfc +private func __nsThunk19(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.double(0) + let a1 = rt.double(1) + let result: SwiftDemo.Point = SwiftDemo.Point(x: a0, y: a1) + rt.returnObject(__NSBox(result), 3) +} + +// s:9SwiftDemo5PointV1xSdvp +private func __nsThunk20(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Point") } + let result: Double = box.value.`x` + rt.returnDouble(Double(result)) +} + +// s:9SwiftDemo5PointV1xSdvp (setter) +private func __nsThunk21(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Point") } + let newValue = rt.double(1) + box.value.`x` = newValue + rt.returnVoid() +} + +// s:9SwiftDemo5PointV1ySdvp +private func __nsThunk22(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Point") } + let result: Double = box.value.`y` + rt.returnDouble(Double(result)) +} + +// s:9SwiftDemo5PointV1ySdvp (setter) +private func __nsThunk23(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Point") } + let newValue = rt.double(1) + box.value.`y` = newValue + rt.returnVoid() +} + +// s:9SwiftDemo5PointV6lengthSdvp +private func __nsThunk24(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let box = rt.object(0) as? __NSBox else { return rt.throwTypeError("receiver must be SwiftDemo.Point") } + let result: Double = box.value.`length` + rt.returnDouble(Double(result)) +} + +// s:9SwiftDemo5shoutySSSgACF +private func __nsThunk25(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.isNull(0) ? nil : rt.string(0) + let result: String? = SwiftDemo.`shout`(a0) + if let result { + rt.returnString(result) + } else { + rt.returnNull() + } +} + +// s:9SwiftDemo6FlavorO11descriptionSSvp +private func __nsThunk26(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = __nsEnum5(rt.string(0)) else { return rt.throwTypeError("receiver must be SwiftDemo.Flavor") } + let result: String = receiver.`description` + rt.returnString(result) +} + +// s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc +private func __nsThunk27(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = Int(truncatingIfNeeded: rt.int64(0)) + let result: SwiftDemo.Flavor? = SwiftDemo.Flavor(rawValue: a0) + if let result { + rt.returnString(__nsEnumName5(result)) + } else { + rt.returnNull() + } +} + +// s:9SwiftDemo6LoaderC10modernOnlyyyF +private func __nsThunk28(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard #available(iOS 16.0, *) else { return rt.throwMessage("modernOnly() requires iOS 16.0") } + guard let receiver = rt.object(0) as? SwiftDemo.Loader else { return rt.throwTypeError("receiver must be SwiftDemo.Loader") } + let _: Void = receiver.`modernOnly`() + rt.returnVoid() +} + +// s:9SwiftDemo6LoaderC11legacyFetchyyF +private func __nsThunk29(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Loader else { return rt.throwTypeError("receiver must be SwiftDemo.Loader") } + let _: Void = receiver.`legacyFetch`() + rt.returnVoid() +} + +// s:9SwiftDemo6LoaderC8oldFetchyyF +private func __nsThunk30(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Loader else { return rt.throwTypeError("receiver must be SwiftDemo.Loader") } + let _: Void = receiver.`oldFetch`() + rt.returnVoid() +} + +// s:9SwiftDemo6LoaderCACycfc +private func __nsThunk31(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Loader = SwiftDemo.Loader() + rt.returnObject(result, __nsTypeIndex(result, 6)) +} + +// s:9SwiftDemo6SquareC4areaSdvp +private func __nsThunk32(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Square else { return rt.throwTypeError("receiver must be SwiftDemo.Square") } + let result: Double = receiver.`area` + rt.returnDouble(Double(result)) +} + +// s:9SwiftDemo6SquareC4sideACSd_tcfc +private func __nsThunk33(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.double(0) + let result: SwiftDemo.Square = SwiftDemo.Square(side: a0) + rt.returnObject(result, __nsTypeIndex(result, 7)) +} + +// s:9SwiftDemo6SquareC4sideSdvp +private func __nsThunk34(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Square else { return rt.throwTypeError("receiver must be SwiftDemo.Square") } + let result: Double = receiver.`side` + rt.returnDouble(Double(result)) +} + +// s:9SwiftDemo6SquareC4sideSdvp (setter) +private func __nsThunk35(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Square else { return rt.throwTypeError("receiver must be SwiftDemo.Square") } + let newValue = rt.double(1) + receiver.`side` = newValue + rt.returnVoid() +} + +// s:9SwiftDemo6SquareC5greet4nameS2S_tF +private func __nsThunk36(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Square else { return rt.throwTypeError("receiver must be SwiftDemo.Square") } + let a0 = rt.string(1) + let result: String = receiver.`greet`(name: a0) + rt.returnString(result) +} + +// s:9SwiftDemo6SquareC5scale2byySd_tF +private func __nsThunk37(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Square else { return rt.throwTypeError("receiver must be SwiftDemo.Square") } + let a0 = rt.double(1) + let _: Void = receiver.`scale`(by: a0) + rt.returnVoid() +} + +// s:9SwiftDemo6SquareC5sidesSivpZ +private func __nsThunk38(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: Int = SwiftDemo.Square.`sides` + rt.returnInt64(Int64(result)) +} + +// s:9SwiftDemo7CounterC5labelSSyF +private func __nsThunk39(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Counter else { return rt.throwTypeError("receiver must be SwiftDemo.Counter") } + let result: String = receiver.`label`() + rt.returnString(result) +} + +// s:9SwiftDemo7CounterCACycfc +private func __nsThunk40(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Counter = SwiftDemo.Counter() + rt.returnObject(result, __nsTypeIndex(result, 8)) +} + +// s:9SwiftDemo7PolygonC11vertexCountSivp +private func __nsThunk41(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Polygon else { return rt.throwTypeError("receiver must be SwiftDemo.Polygon") } + let result: Int = receiver.`vertexCount` + rt.returnInt64(Int64(result)) +} + +// s:9SwiftDemo7PolygonC4makeACyFZ +private func __nsThunk42(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Polygon = SwiftDemo.Polygon.`make`() + rt.returnObject(result, __nsTypeIndex(result, 9)) +} + +// s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc +private func __nsThunk43(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.string(0) + let a1 = Int(truncatingIfNeeded: rt.int64(1)) + let result: SwiftDemo.Polygon = SwiftDemo.Polygon(name: a0, vertexCount: a1) + rt.returnObject(result, __nsTypeIndex(result, 9)) +} + +// s:9SwiftDemo7PolygonC4nameACSgSS_tcfc +private func __nsThunk44(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = rt.string(0) + let result: SwiftDemo.Polygon? = SwiftDemo.Polygon(name: a0) + if let result { + rt.returnObject(result, __nsTypeIndex(result, 9)) + } else { + rt.returnNull() + } +} + +// s:9SwiftDemo7PolygonC4nameSSvp +private func __nsThunk45(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Polygon else { return rt.throwTypeError("receiver must be SwiftDemo.Polygon") } + let result: String = receiver.`name` + rt.returnString(result) +} + +// s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF +private func __nsThunk46(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Polygon else { return rt.throwTypeError("receiver must be SwiftDemo.Polygon") } + let a0 = rt.double(1) + let a1 = rt.double(2) + let _: Void = receiver.`scale`(x: a0, y: a1) + rt.returnVoid() +} + +// s:9SwiftDemo7PolygonC5scale2byySd_tF +private func __nsThunk47(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Polygon else { return rt.throwTypeError("receiver must be SwiftDemo.Polygon") } + let a0 = rt.double(1) + let _: Void = receiver.`scale`(by: a0) + rt.returnVoid() +} + +// s:9SwiftDemo7PolygonC5scale2byySi_tF +private func __nsThunk48(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Polygon else { return rt.throwTypeError("receiver must be SwiftDemo.Polygon") } + let a0 = Int(truncatingIfNeeded: rt.int64(1)) + let _: Void = receiver.`scale`(by: a0) + rt.returnVoid() +} + +// s:9SwiftDemo7PolygonC6sharedACvpZ +private func __nsThunk49(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: SwiftDemo.Polygon = SwiftDemo.Polygon.`shared` + rt.returnObject(result, __nsTypeIndex(result, 9)) +} + +// s:9SwiftDemo7PolygonC8describeySSACSgFZ +private func __nsThunk50(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + var a0: SwiftDemo.Polygon? = nil + if !rt.isNull(0) { + guard let value = rt.object(0) as? SwiftDemo.Polygon else { return rt.throwTypeError("argument 1 must be SwiftDemo.Polygon") } + a0 = value + } + let result: String = SwiftDemo.Polygon.`describe`(a0) + rt.returnString(result) +} + +// s:9SwiftDemo7TrackerC2idACSi_tcfc +private func __nsThunk51(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = Int(truncatingIfNeeded: rt.int64(0)) + let result: SwiftDemo.Tracker = SwiftDemo.Tracker(id: a0) + rt.returnObject(result, __nsTypeIndex(result, 10)) +} + +// s:9SwiftDemo7TrackerC2idSivp +private func __nsThunk52(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Tracker else { return rt.throwTypeError("receiver must be SwiftDemo.Tracker") } + let result: Int = receiver.`id` + rt.returnInt64(Int64(result)) +} + +// s:9SwiftDemo7TrackerC4sameACyF +private func __nsThunk53(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = rt.object(0) as? SwiftDemo.Tracker else { return rt.throwTypeError("receiver must be SwiftDemo.Tracker") } + let result: SwiftDemo.Tracker = receiver.`same`() + rt.returnObject(result, __nsTypeIndex(result, 10)) +} + +// s:9SwiftDemo7TrackerC9liveCountSivpZ +private func __nsThunk54(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let result: Int = SwiftDemo.Tracker.`liveCount` + rt.returnInt64(Int64(result)) +} + +// s:9SwiftDemo8echoInt8ys0D0VADF +private func __nsThunk55(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + let a0 = Int8(truncatingIfNeeded: rt.int64(0)) + let result: Int8 = SwiftDemo.`echoInt8`(a0) + rt.returnInt64(Int64(result)) +} + +// s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO +private func __nsThunk56(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = __nsEnum1(rt.string(0)) else { return rt.throwTypeError("receiver must be SwiftDemo.Precipitation") } + let result: Int = receiver.`hashValue` + rt.returnInt64(Int64(result)) +} + +// s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO +private func __nsThunk57(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ count: Int) { + let rt = __NSCall(call: call, args: args) + guard let receiver = __nsEnum5(rt.string(0)) else { return rt.throwTypeError("receiver must be SwiftDemo.Flavor") } + let result: Int = receiver.`hashValue` + rt.returnInt64(Int64(result)) +} + +#if hasAttribute(c) +@c(ns_swift_register_SwiftDemo) +#else +@_cdecl("ns_swift_register_SwiftDemo") +#endif +public func __nsRegister_SwiftDemo(_ registrar: UnsafeMutableRawPointer) { + let api = registrar.load(as: UnsafeRawPointer.self) + let registerModule = api.load(fromByteOffset: 80, as: (@convention(c) (UnsafeMutableRawPointer, UInt32, UnsafePointer, UnsafePointer, __NSRelease) -> Void).self) + let registerType = api.load(fromByteOffset: 88, as: (@convention(c) (UnsafeMutableRawPointer, UInt32, UInt32, UnsafePointer, UnsafePointer, Int32) -> Void).self) + let registerMember = api.load(fromByteOffset: 96, as: (@convention(c) (UnsafeMutableRawPointer, Int32, UInt32, UInt32, UnsafePointer, UnsafePointer, UnsafePointer, __NSThunk?, __NSThunk?) -> Void).self) + + registerModule(registrar, 1, "SwiftDemo", "619ecd8bdf28f35a", __nsRelease) + registerType(registrar, 0, 0, "Demo", "SwiftDemo.Demo", -1) + registerType(registrar, 1, 3, "Precipitation", "SwiftDemo.Precipitation", -1) + registerType(registrar, 2, 2, "Ring", "SwiftDemo.Ring", -1) + registerType(registrar, 3, 2, "Point", "SwiftDemo.Point", -1) + registerType(registrar, 4, 0, "Canvas", "SwiftDemo.Canvas", -1) + registerType(registrar, 5, 3, "Flavor", "SwiftDemo.Flavor", -1) + registerType(registrar, 6, 0, "Loader", "SwiftDemo.Loader", -1) + registerType(registrar, 7, 0, "Square", "SwiftDemo.Square", 9) + registerType(registrar, 8, 1, "Counter", "SwiftDemo.Counter", -1) + registerType(registrar, 9, 0, "Polygon", "SwiftDemo.Polygon", -1) + registerType(registrar, 10, 0, "Tracker", "SwiftDemo.Tracker", -1) + registerMember(registrar, 0, 1, 0, "greet", "greet(name:times:)", "s,i64>s", __nsThunk0, nil) + registerMember(registrar, 0, 1, 0, "greet", "greet(name:)", "s>s", __nsThunk1, nil) + registerMember(registrar, 0, 4, 0, "version", "version", ">s", __nsThunk2, nil) + registerMember(registrar, 0, 0, 0, "constructor", "init()", ">o0", __nsThunk3, nil) + registerMember(registrar, -1, 5, 0, "echoUInt64", "echoUInt64(_:)", "u64>u64", __nsThunk4, nil) + registerMember(registrar, -1, 5, 0, "largestInt", "largestInt()", ">i64", __nsThunk5, nil) + registerMember(registrar, -1, 5, 1, "checkedSide", "checkedSide(_:)", "f64>f64", __nsThunk6, nil) + registerMember(registrar, 1, 7, 0, "none", "none", ">e1", nil, nil) + registerMember(registrar, 1, 7, 0, "rain", "rain", ">e1", nil, nil) + registerMember(registrar, 1, 7, 0, "snow", "snow", ">e1", nil, nil) + registerMember(registrar, 1, 0, 0, "constructor", "init(rawValue:)", "s>e1?", __nsThunk7, nil) + registerMember(registrar, -1, 6, 0, "defaultFlavor", "defaultFlavor", ">e5", __nsThunk8, nil) + registerMember(registrar, -1, 6, 2, "globalCounter", "globalCounter", ">i64", __nsThunk9, __nsThunk10) + registerMember(registrar, -1, 5, 0, "makeDefaultPoint", "makeDefaultPoint()", ">o3", __nsThunk11, nil) + registerMember(registrar, 2, 0, 0, "constructor", "init(inner:outer:)", "o3,o3>o2", __nsThunk12, nil) + registerMember(registrar, 2, 3, 2, "inner", "inner", ">o3", __nsThunk13, __nsThunk14) + registerMember(registrar, 2, 3, 2, "outer", "outer", ">o3", __nsThunk15, __nsThunk16) + registerMember(registrar, 2, 1, 0, "expand", "expand(by:)", "f64>v", __nsThunk17, nil) + registerMember(registrar, 3, 3, 0, "description", "description", ">s", __nsThunk18, nil) + registerMember(registrar, 3, 0, 0, "constructor", "init(x:y:)", "f64,f64>o3", __nsThunk19, nil) + registerMember(registrar, 3, 3, 2, "x", "x", ">f64", __nsThunk20, __nsThunk21) + registerMember(registrar, 3, 3, 2, "y", "y", ">f64", __nsThunk22, __nsThunk23) + registerMember(registrar, 3, 3, 0, "length", "length", ">f64", __nsThunk24, nil) + registerMember(registrar, -1, 5, 0, "shout", "shout(_:)", "s?>s?", __nsThunk25, nil) + registerMember(registrar, 5, 3, 0, "description", "description", ">s", __nsThunk26, nil) + registerMember(registrar, 5, 7, 0, "vanilla", "vanilla", ">e5", nil, nil) + registerMember(registrar, 5, 0, 0, "constructor", "init(rawValue:)", "i64>e5?", __nsThunk27, nil) + registerMember(registrar, 5, 7, 0, "chocolate", "chocolate", ">e5", nil, nil) + registerMember(registrar, 6, 1, 0, "modernOnly", "modernOnly()", ">v", __nsThunk28, nil) + registerMember(registrar, 6, 1, 0, "legacyFetch", "legacyFetch()", ">v", __nsThunk29, nil) + registerMember(registrar, 6, 1, 0, "oldFetch", "oldFetch()", ">v", __nsThunk30, nil) + registerMember(registrar, 6, 0, 0, "constructor", "init()", ">o6", __nsThunk31, nil) + registerMember(registrar, 7, 3, 0, "area", "area", ">f64", __nsThunk32, nil) + registerMember(registrar, 7, 0, 0, "constructor", "init(side:)", "f64>o7", __nsThunk33, nil) + registerMember(registrar, 7, 3, 2, "side", "side", ">f64", __nsThunk34, __nsThunk35) + registerMember(registrar, 7, 1, 0, "greet", "greet(name:)", "s>s", __nsThunk36, nil) + registerMember(registrar, 7, 1, 0, "scale", "scale(by:)", "f64>v", __nsThunk37, nil) + registerMember(registrar, 7, 4, 0, "sides", "sides", ">i64", __nsThunk38, nil) + registerMember(registrar, 8, 1, 0, "label", "label()", ">s", __nsThunk39, nil) + registerMember(registrar, 8, 0, 0, "constructor", "init()", ">o8", __nsThunk40, nil) + registerMember(registrar, 9, 3, 0, "vertexCount", "vertexCount", ">i64", __nsThunk41, nil) + registerMember(registrar, 9, 2, 0, "make", "make()", ">o9", __nsThunk42, nil) + registerMember(registrar, 9, 0, 0, "constructor", "init(name:vertexCount:)", "s,i64>o9", __nsThunk43, nil) + registerMember(registrar, 9, 0, 0, "constructor", "init(name:)", "s>o9?", __nsThunk44, nil) + registerMember(registrar, 9, 3, 0, "name", "name", ">s", __nsThunk45, nil) + registerMember(registrar, 9, 1, 0, "scale", "scale(x:y:)", "f64,f64>v", __nsThunk46, nil) + registerMember(registrar, 9, 1, 4, "scale", "scale(by:)", "f64>v", __nsThunk47, nil) + registerMember(registrar, 9, 1, 4, "scale", "scale(by:)", "i64>v", __nsThunk48, nil) + registerMember(registrar, 9, 4, 0, "shared", "shared", ">o9", __nsThunk49, nil) + registerMember(registrar, 9, 2, 0, "describe", "describe(_:)", "o9?>s", __nsThunk50, nil) + registerMember(registrar, 10, 0, 0, "constructor", "init(id:)", "i64>o10", __nsThunk51, nil) + registerMember(registrar, 10, 3, 0, "id", "id", ">i64", __nsThunk52, nil) + registerMember(registrar, 10, 1, 0, "same", "same()", ">o10", __nsThunk53, nil) + registerMember(registrar, 10, 4, 0, "liveCount", "liveCount", ">i64", __nsThunk54, nil) + registerMember(registrar, -1, 5, 0, "echoInt8", "echoInt8(_:)", "i8>i8", __nsThunk55, nil) + registerMember(registrar, 1, 3, 0, "hashValue", "hashValue", ">i64", __nsThunk56, nil) + registerMember(registrar, 5, 3, 0, "hashValue", "hashValue", ">i64", __nsThunk57, nil) +} diff --git a/metadata-generator/TestFixtures/SwiftDemo/Package.swift b/metadata-generator/TestFixtures/SwiftDemo/Package.swift index 214748ca7..6ddba2a1e 100644 --- a/metadata-generator/TestFixtures/SwiftDemo/Package.swift +++ b/metadata-generator/TestFixtures/SwiftDemo/Package.swift @@ -4,8 +4,14 @@ import PackageDescription let package = Package( name: "SwiftDemo", platforms: [ .iOS(.v15) ], - products: [ .library(name: "SwiftDemo", targets: ["SwiftDemo"]) ], + products: [ + .library(name: "SwiftDemo", targets: ["SwiftDemo"]), + // The generated NativeScript thunks, compiled as their own module so + // they reach SwiftDemo only through its public interface. + .library(name: "SwiftDemoInterop", targets: ["SwiftDemoInterop"]), + ], targets: [ - .target(name: "SwiftDemo", path: "Sources") + .target(name: "SwiftDemo", path: "Sources/SwiftDemo"), + .target(name: "SwiftDemoInterop", dependencies: ["SwiftDemo"], path: "Interop"), ] ) diff --git a/metadata-generator/TestFixtures/SwiftDemo/README.md b/metadata-generator/TestFixtures/SwiftDemo/README.md index 81e822bd1..4ad06c1d9 100644 --- a/metadata-generator/TestFixtures/SwiftDemo/README.md +++ b/metadata-generator/TestFixtures/SwiftDemo/README.md @@ -13,8 +13,14 @@ changing `Sources/`, regenerate the graphs and then the test snapshots: ``` ./generate-symbolgraphs.sh -NS_UPDATE_SNAPSHOTS=1 ../../build/bin/swift-symbolgraph-tests Snapshot +NS_UPDATE_SNAPSHOTS=1 ../../build/bin/swift-symbolgraph-tests ``` Review the resulting snapshot diff before committing it; it is the record of what the loader extracts. + +`Interop/SwiftDemo+NativeScript.swift` holds the generated thunks (regenerated +by the same `NS_UPDATE_SNAPSHOTS=1` run). TestRunner compiles it with the +fixture sources and exercises it from `TestRunner/app/tests/SwiftInteropTests.js`; +`Package.swift` builds the same files as two SwiftPM modules (`SwiftDemo` and +`SwiftDemoInterop`). diff --git a/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift index 6bb24ec62..0a6f1ec82 100644 --- a/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift +++ b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Shapes.swift @@ -47,6 +47,11 @@ public final class Square: Polygon, Shape { override public func scale(by factor: Double) { side *= factor } } +// A case named `none` must not be confused with Optional.none. +public enum Precipitation: String { + case rain, snow, none +} + public enum ShapeError: Error { case invalidSide(Double) case tooManySides(count: Int, limit: Int) diff --git a/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Values.swift b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Values.swift new file mode 100644 index 000000000..4036b478c --- /dev/null +++ b/metadata-generator/TestFixtures/SwiftDemo/Sources/SwiftDemo/Values.swift @@ -0,0 +1,26 @@ +// Declarations the runtime tests use to exercise value marshaling, errors and +// object lifetime. + +public func checkedSide(_ side: Double) throws -> Double { + if side < 0 { throw ShapeError.invalidSide(side) } + return side +} + +public func echoInt8(_ value: Int8) -> Int8 { value } +public func echoUInt64(_ value: UInt64) -> UInt64 { value } +public func largestInt() -> Int { Int.max } +public func shout(_ name: String?) -> String? { name.map { $0.uppercased() } } + +public final class Tracker { + public private(set) static var liveCount = 0 + public let id: Int + + public init(id: Int) { + self.id = id + Tracker.liveCount += 1 + } + + deinit { Tracker.liveCount -= 1 } + + public func same() -> Tracker { self } +} diff --git a/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json b/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json index 818798d3b..141d999da 100644 --- a/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json +++ b/metadata-generator/TestFixtures/SwiftDemo/symbolgraphs/SwiftDemo.symbols.json @@ -1 +1 @@ -{"metadata":{"formatVersion":{"major":0,"minor":6,"patch":0},"generator":"Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)"},"module":{"name":"SwiftDemo","platform":{"architecture":"arm64","environment":"simulator","vendor":"apple","operatingSystem":{"name":"ios","minimumVersion":{"major":15,"minor":0}}}},"symbols":[{"kind":{"identifier":"swift.protocol","displayName":"Protocol"},"identifier":{"precise":"s:9SwiftDemo7GreeterP","interfaceLanguage":"swift"},"pathComponents":["Greeter"],"names":{"title":"Greeter","navigator":[{"kind":"identifier","spelling":"Greeter"}],"subHeading":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Greeter"}]},"declarationFragments":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Greeter"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":0,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Greeter","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":1,"character":9}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo0B0C","interfaceLanguage":"swift"},"pathComponents":["Demo"],"names":{"title":"Demo","navigator":[{"kind":"identifier","spelling":"Demo"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Demo"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Demo"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":4,"character":13}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo0B0CACycfc","interfaceLanguage":"swift"},"pathComponents":["Demo","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":5,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo0B0C5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Demo","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":6,"character":16}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo5PointV","interfaceLanguage":"swift"},"pathComponents":["Point"],"names":{"title":"Point","navigator":[{"kind":"identifier","spelling":"Point"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Point"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Point"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":9,"character":14}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV1xSdvp","interfaceLanguage":"swift"},"pathComponents":["Point","x"],"names":{"title":"x","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":10,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV1ySdvp","interfaceLanguage":"swift"},"pathComponents":["Point","y"],"names":{"title":"y","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":11,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo5PointV1x1yACSd_Sdtcfc","interfaceLanguage":"swift"},"pathComponents":["Point","init(x:y:)"],"names":{"title":"init(x:y:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"x","declarationFragments":[{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},{"name":"y","declarationFragments":[{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":12,"character":11}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor"],"names":{"title":"Flavor","navigator":[{"kind":"identifier","spelling":"Flavor"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Flavor"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Flavor"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","hashValue"],"names":{"title":"hashValue","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","hash(into:)"],"names":{"title":"hash(into:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"into","internalName":"hasher","declarationFragments":[{"kind":"identifier","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftGenerics":{"constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","!=(_:_:)"],"names":{"title":"!=(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"docComment":{"module":"Swift","lines":[{"text":"Returns a Boolean value indicating whether two values are not equal."},{"text":""},{"text":"Inequality is the inverse of equality. For any values `a` and `b`, `a != b`"},{"text":"implies that `a == b` is `false`."},{"text":""},{"text":"This is the default implementation of the not-equal-to operator (`!=`)"},{"text":"for any type that conforms to `Equatable`."},{"text":""},{"text":"- Parameters:"},{"text":" - lhs: A value to compare."},{"text":" - rhs: Another value to compare."}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}],"accessLevel":"public"},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo6FlavorO7vanillayA2CmF","interfaceLanguage":"swift"},"pathComponents":["Flavor","vanilla"],"names":{"title":"Flavor.vanilla","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vanilla"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vanilla"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":31}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo6FlavorO9chocolateyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Flavor","chocolate"],"names":{"title":"Flavor.chocolate","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"chocolate"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"chocolate"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":44}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc","interfaceLanguage":"swift"},"pathComponents":["Flavor","init(rawValue:)"],"names":{"title":"init(rawValue:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"rawValue","declarationFragments":[{"kind":"identifier","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo0B0C5greet4name5timesS2S_SitF","interfaceLanguage":"swift"},"pathComponents":["Demo","greet(name:times:)"],"names":{"title":"greet(name:times:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"times","declarationFragments":[{"kind":"identifier","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.class"},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":1,"character":16}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo0B0C7versionSSvpZ","interfaceLanguage":"swift"},"pathComponents":["Demo","version"],"names":{"title":"version","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"version"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.class"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"version"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":5,"character":22}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV11descriptionSSvp","interfaceLanguage":"swift"},"pathComponents":["Point","description"],"names":{"title":"description","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":9,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV6lengthSdvp","interfaceLanguage":"swift"},"pathComponents":["Point","length"],"names":{"title":"length","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":10,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6FlavorO11descriptionSSvp","interfaceLanguage":"swift"},"pathComponents":["Flavor","description"],"names":{"title":"description","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.enum"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":14,"character":15}}},{"kind":{"identifier":"swift.protocol","displayName":"Protocol"},"identifier":{"precise":"s:9SwiftDemo5ShapeP","interfaceLanguage":"swift"},"pathComponents":["Shape"],"names":{"title":"Shape","navigator":[{"kind":"identifier","spelling":"Shape"}],"subHeading":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Shape"}]},"declarationFragments":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Shape"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Greeter","preciseIdentifier":"s:9SwiftDemo7GreeterP"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":2,"character":16}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5ShapeP4areaSdvp","interfaceLanguage":"swift"},"pathComponents":["Shape","area"],"names":{"title":"area","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":3,"character":8}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo5ShapeP5sidesSivpZ","interfaceLanguage":"swift"},"pathComponents":["Shape","sides"],"names":{"title":"sides","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":4,"character":15}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7PolygonC","interfaceLanguage":"swift"},"pathComponents":["Polygon"],"names":{"title":"Polygon","navigator":[{"kind":"identifier","spelling":"Polygon"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Polygon"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Polygon"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":7,"character":11}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4nameSSvp","interfaceLanguage":"swift"},"pathComponents":["Polygon","name"],"names":{"title":"name","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":8,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC11vertexCountSivp","interfaceLanguage":"swift"},"pathComponents":["Polygon","vertexCount"],"names":{"title":"vertexCount","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":9,"character":28}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC6sharedACvpZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","shared"],"names":{"title":"shared","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shared"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shared"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":10,"character":22}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc","interfaceLanguage":"swift"},"pathComponents":["Polygon","init(name:vertexCount:)"],"names":{"title":"init(name:vertexCount:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"vertexCount","declarationFragments":[{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":12,"character":11}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4nameACSgSS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Polygon","init(name:)"],"names":{"title":"init(name:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"convenience"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":17,"character":23}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":22,"character":14}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale2byySi_tF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":23,"character":14}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(x:y:)"],"names":{"title":"scale(x:y:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"x","declarationFragments":[{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},{"name":"y","declarationFragments":[{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":24,"character":16}}},{"kind":{"identifier":"swift.type.method","displayName":"Type Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4makeACyFZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","make()"],"names":{"title":"make()","subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"make"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"make"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":26,"character":22}}},{"kind":{"identifier":"swift.type.method","displayName":"Type Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC8describeySSACSgFZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","describe(_:)"],"names":{"title":"describe(_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"describe"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"polygon","declarationFragments":[{"kind":"identifier","spelling":"polygon"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"describe"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"polygon"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":27,"character":23}}},{"kind":{"identifier":"swift.subscript","displayName":"Instance Subscript"},"identifier":{"precise":"s:9SwiftDemo7PolygonCyAA5PointVSicip","interfaceLanguage":"swift"},"pathComponents":["Polygon","subscript(_:)"],"names":{"title":"subscript(_:)","subHeading":[{"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"parameters":[{"name":"index","declarationFragments":[{"kind":"identifier","spelling":"index"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"index"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":29,"character":11}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6SquareC","interfaceLanguage":"swift"},"pathComponents":["Square"],"names":{"title":"Square","navigator":[{"kind":"identifier","spelling":"Square"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Square"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Square"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":34,"character":19}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC4sideSdvp","interfaceLanguage":"swift"},"pathComponents":["Square","side"],"names":{"title":"side","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":35,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6SquareC4sideACSd_tcfc","interfaceLanguage":"swift"},"pathComponents":["Square","init(side:)"],"names":{"title":"init(side:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"side","declarationFragments":[{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":37,"character":11}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC4areaSdvp","interfaceLanguage":"swift"},"pathComponents":["Square","area"],"names":{"title":"area","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":42,"character":15}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC5sidesSivpZ","interfaceLanguage":"swift"},"pathComponents":["Square","sides"],"names":{"title":"sides","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":43,"character":22}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6SquareC5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Square","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":44,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6SquareC5scale2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Square","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"override"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":46,"character":25}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO","interfaceLanguage":"swift"},"pathComponents":["ShapeError"],"names":{"title":"ShapeError","navigator":[{"kind":"identifier","spelling":"ShapeError"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"ShapeError"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"ShapeError"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":49,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO","interfaceLanguage":"swift"},"pathComponents":["ShapeError","localizedDescription"],"names":{"title":"localizedDescription","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"localizedDescription"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"docComment":{"module":"Foundation","lines":[{"text":"Retrieve the localized description for this error."}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"localizedDescription"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":8,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":10}},{"domain":"tvOS","introduced":{"major":9,"minor":0}},{"domain":"watchOS","introduced":{"major":2,"minor":0}}]},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","invalidSide(_:)"],"names":{"title":"ShapeError.invalidSide(_:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"invalidSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"invalidSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":50,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","tooManySides(count:limit:)"],"names":{"title":"ShapeError.tooManySides(count:limit:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"tooManySides"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"count"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"limit"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"tooManySides"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"count"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"limit"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":51,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO7unknownyA2CmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","unknown"],"names":{"title":"ShapeError.unknown","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"unknown"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"unknown"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":52,"character":9}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO","interfaceLanguage":"swift"},"pathComponents":["Measurement"],"names":{"title":"Measurement","navigator":[{"kind":"identifier","spelling":"Measurement"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Measurement"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Measurement"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":55,"character":12}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO6lengthyACSdcACmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","length(_:)"],"names":{"title":"Measurement.length(_:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":56,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","area(width:height:)"],"names":{"title":"Measurement.area(width:height:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"width"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"height"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"width"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"height"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":57,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4noneyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","none"],"names":{"title":"Measurement.none","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":58,"character":9}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit"],"names":{"title":"Measurement.Unit","navigator":[{"kind":"identifier","spelling":"Unit"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Unit"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Unit"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":60,"character":18}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit","symbol"],"names":{"title":"symbol","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":61,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit","init(symbol:)"],"names":{"title":"init(symbol:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"symbol","declarationFragments":[{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":62,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO6isNoneSbvp","interfaceLanguage":"swift"},"pathComponents":["Measurement","isNone"],"names":{"title":"isNone","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"isNone"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"isNone"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":65,"character":15}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo4RingV","interfaceLanguage":"swift"},"pathComponents":["Ring"],"names":{"title":"Ring","navigator":[{"kind":"identifier","spelling":"Ring"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Ring"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Ring"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":71,"character":14}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo4RingV5innerAA5PointVvp","interfaceLanguage":"swift"},"pathComponents":["Ring","inner"],"names":{"title":"inner","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":72,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo4RingV5outerAA5PointVvp","interfaceLanguage":"swift"},"pathComponents":["Ring","outer"],"names":{"title":"outer","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":73,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc","interfaceLanguage":"swift"},"pathComponents":["Ring","init(inner:outer:)"],"names":{"title":"init(inner:outer:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"inner","declarationFragments":[{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},{"name":"outer","declarationFragments":[{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":75,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo4RingV6expand2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Ring","expand(by:)"],"names":{"title":"expand(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"expand"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"delta","declarationFragments":[{"kind":"identifier","spelling":"delta"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"mutating"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"expand"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"delta"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":80,"character":25}}},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:9SwiftDemo4RingV1poiyA2C_ACtFZ","interfaceLanguage":"swift"},"pathComponents":["Ring","+(_:_:)"],"names":{"title":"+(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"+"},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"+"},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":85,"character":23}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter"],"names":{"title":"Counter","navigator":[{"kind":"identifier","spelling":"Counter"}],"subHeading":[{"kind":"keyword","spelling":"actor"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Counter"}]},"declarationFragments":[{"kind":"keyword","spelling":"actor"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Counter"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":90,"character":13}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","withSerialExecutor(_:)"],"names":{"title":"withSerialExecutor(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">((any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Perform an operation with the actor's ``SerialExecutor``."},{"text":""},{"text":"This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while"},{"text":"retaining the actor for the duration of the operation. This is to ensure the lifetime"},{"text":"of the executor while performing the operation."}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1},{"name":"E","index":1,"depth":1}],"constraints":[{"kind":"conformance","lhs":"E","rhs":"Error","rhsPrecise":"s:s5ErrorP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Error","preciseIdentifier":"s:s5ErrorP"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : ~Copyable"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","withSerialExecutor(_:)"],"names":{"title":"withSerialExecutor(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"keyword","spelling":"nonisolated(nonsending)"},{"kind":"text","spelling":" (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Perform an operation with the actor's ``SerialExecutor``."},{"text":""},{"text":"This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while"},{"text":"retaining the actor for the duration of the operation. This is to ensure the lifetime"},{"text":"of the executor while performing the operation."}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1},{"name":"E","index":1,"depth":1}],"constraints":[{"kind":"conformance","lhs":"E","rhs":"Error","rhsPrecise":"s:s5ErrorP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"nonisolated(nonsending)"},{"kind":"text","spelling":" (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Error","preciseIdentifier":"s:s5ErrorP"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : ~Copyable"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","preconditionIsolated(_:file:line:)"],"names":{"title":"preconditionIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"preconditionIsolated"},{"kind":"text","spelling":"("},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":")"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Stops program execution if the current task is not executing on this"},{"text":"actor's serial executor."},{"text":""},{"text":"This function's effect varies depending on the build flag used:"},{"text":""},{"text":"* In playgrounds and `-Onone` builds (the default for Xcode's Debug"},{"text":" configuration), stops program execution in a debuggable state after"},{"text":" printing `message`."},{"text":""},{"text":"* In `-O` builds (the default for Xcode's Release configuration), stops"},{"text":" program execution."},{"text":""},{"text":"- Note: Because this check is performed against the actor's serial executor,"},{"text":" if another actor uses the same serial executor--by using"},{"text":" that actor's serial executor as its own ``Actor/unownedExecutor``--this"},{"text":" check will succeed. From a concurrency safety perspective, the"},{"text":" serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - message: The message to print if the assertion fails."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."}]},"functionSignature":{"parameters":[{"name":"message","declarationFragments":[{"kind":"identifier","spelling":"message"},{"kind":"text","spelling":": () -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"text","spelling":"@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\n"},{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"preconditionIsolated"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"message"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" = String(), "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":")"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","assertIsolated(_:file:line:)"],"names":{"title":"assertIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assertIsolated"},{"kind":"text","spelling":"("},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":")"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Stops program execution if the current task is not executing on this"},{"text":"actor's serial executor."},{"text":""},{"text":"This function's effect varies depending on the build flag used:"},{"text":""},{"text":"* In playgrounds and `-Onone` builds (the default for Xcode's Debug"},{"text":" configuration), stops program execution in a debuggable state after"},{"text":" printing `message`."},{"text":""},{"text":"* In `-O` builds (the default for Xcode's Release configuration),"},{"text":" the isolation check is not performed and there are no effects."},{"text":""},{"text":"- Note: This check is performed against the actor's serial executor,"},{"text":" meaning that / if another actor uses the same serial executor--by using"},{"text":" that actor's serial executor as its own ``Actor/unownedExecutor``--this"},{"text":" check will succeed , as from a concurrency safety perspective, the"},{"text":" serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - message: The message to print if the assertion fails."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."}]},"functionSignature":{"parameters":[{"name":"message","declarationFragments":[{"kind":"identifier","spelling":"message"},{"kind":"text","spelling":": () -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"text","spelling":"@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\n"},{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assertIsolated"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"message"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" = String(), "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":")"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","assumeIsolated(_:file:line:)"],"names":{"title":"assumeIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assumeIsolated"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">(("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"rethrows"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Assume that the current task is executing on this actor's serial executor,"},{"text":"or stop program execution otherwise."},{"text":""},{"text":"You call this method to *assume and verify* that the currently"},{"text":"executing synchronous function is actually executing on the serial"},{"text":"executor of this actor."},{"text":""},{"text":"If that is the case, the operation is invoked with an `isolated` version"},{"text":"of the actor, allowing synchronous access to actor local state without"},{"text":"hopping through asynchronous boundaries."},{"text":""},{"text":"If the current context is not running on the actor's serial executor, or"},{"text":"if the actor is a reference to a remote actor, this method will crash"},{"text":"with a fatal error (similar to ``preconditionIsolated(_:file:line:)``)."},{"text":""},{"text":"Note that this check is performed against the passed in actor's serial"},{"text":"executor, meaning that if another actor uses the same serial executor--by"},{"text":"using that actor's ``Actor/unownedExecutor`` as its own"},{"text":"``Actor/unownedExecutor``--this check will succeed, as from a concurrency"},{"text":"safety perspective, the serial executor guarantees mutual exclusion of"},{"text":"those two actors."},{"text":""},{"text":"This method can only be used from synchronous functions, as asynchronous"},{"text":"functions should instead perform a normal method call to the actor, which"},{"text":"will hop task execution to the target actor if necessary."},{"text":""},{"text":"- Note: This check is performed against the actor's serial executor,"},{"text":" meaning that / if another actor uses the same serial executor--by using"},{"text":" another actor's executor as its own ``Actor/unownedExecutor``"},{"text":" --this check will succeed , as from a concurrency safety perspective,"},{"text":" the serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - operation: the operation that will be executed if the current context"},{"text":" is executing on the actors serial executor."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."},{"text":"- Returns: the return value of the `operation`"},{"text":"- Throws: rethrows the `Error` thrown by the operation if it threw"}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": ("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1}],"constraints":[{"kind":"conformance","lhs":"T","rhs":"Sendable","rhsPrecise":"s:s8SendableP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assumeIsolated"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": ("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"rethrows"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Sendable","preciseIdentifier":"s:s8SendableP"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7CounterC5valueSivp","interfaceLanguage":"swift"},"pathComponents":["Counter","value"],"names":{"title":"value","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":91,"character":28}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7CounterCACycfc","interfaceLanguage":"swift"},"pathComponents":["Counter","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":92,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7CounterC9incrementSiyF","interfaceLanguage":"swift"},"pathComponents":["Counter","increment()"],"names":{"title":"increment()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"increment"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"increment"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":93,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7CounterC5labelSSyF","interfaceLanguage":"swift"},"pathComponents":["Counter","label()"],"names":{"title":"label()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"label"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"label"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":97,"character":28}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6CanvasC","interfaceLanguage":"swift"},"pathComponents":["Canvas"],"names":{"title":"Canvas","navigator":[{"kind":"identifier","spelling":"Canvas"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Canvas"}]},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Canvas"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":101,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6CanvasCACycfc","interfaceLanguage":"swift"},"pathComponents":["Canvas","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":102,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF","interfaceLanguage":"swift"},"pathComponents":["Canvas","draw(_:)"],"names":{"title":"draw(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"draw"},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"shape","declarationFragments":[{"kind":"identifier","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"draw"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":103,"character":16}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6LoaderC","interfaceLanguage":"swift"},"pathComponents":["Loader"],"names":{"title":"Loader","navigator":[{"kind":"identifier","spelling":"Loader"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Loader"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Loader"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":106,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6LoaderCACycfc","interfaceLanguage":"swift"},"pathComponents":["Loader","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":107,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF","interfaceLanguage":"swift"},"pathComponents":["Loader","load(path:)"],"names":{"title":"load(path:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}]},"functionSignature":{"parameters":[{"name":"path","declarationFragments":[{"kind":"identifier","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":109,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF","interfaceLanguage":"swift"},"pathComponents":["Loader","fetch(url:)"],"names":{"title":"fetch(url:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"fetch"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"url","declarationFragments":[{"kind":"identifier","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"fetch"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":110,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF","interfaceLanguage":"swift"},"pathComponents":["Loader","wait(seconds:)"],"names":{"title":"wait(seconds:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"wait"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"}]},"functionSignature":{"parameters":[{"name":"seconds","declarationFragments":[{"kind":"identifier","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"wait"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":111,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF","interfaceLanguage":"swift"},"pathComponents":["Loader","transform(_:)"],"names":{"title":"transform(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"transform"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"}]},"functionSignature":{"parameters":[{"name":"shape","declarationFragments":[{"kind":"identifier","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":0}],"constraints":[{"kind":"conformance","lhs":"T","rhs":"Shape","rhsPrecise":"s:9SwiftDemo5ShapeP"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"transform"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":113,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF","interfaceLanguage":"swift"},"pathComponents":["Loader","first(of:)"],"names":{"title":"first(of:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"first"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"Element"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"of"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]) -> "},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"of","internalName":"items","declarationFragments":[{"kind":"identifier","spelling":"items"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Element"},{"kind":"text","spelling":"?"}]},"swiftGenerics":{"parameters":[{"name":"Element","index":0,"depth":0}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"first"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"Element"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"of"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"items"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]) -> "},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":114,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF","interfaceLanguage":"swift"},"pathComponents":["Loader","withCompletion(_:)"],"names":{"title":"withCompletion(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withCompletion"},{"kind":"text","spelling":"(("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"completion","declarationFragments":[{"kind":"identifier","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" ("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withCompletion"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" ("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":116,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4eachyyySiXEF","interfaceLanguage":"swift"},"pathComponents":["Loader","each(_:)"],"names":{"title":"each(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"each"},{"kind":"text","spelling":"(("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"body","declarationFragments":[{"kind":"identifier","spelling":"body"},{"kind":"text","spelling":": ("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"each"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"body"},{"kind":"text","spelling":": ("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":117,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF","interfaceLanguage":"swift"},"pathComponents":["Loader","lookup(table:key:)"],"names":{"title":"lookup(table:key:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"lookup"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"], "},{"kind":"externalParam","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"table","declarationFragments":[{"kind":"identifier","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"]"}]},{"name":"key","declarationFragments":[{"kind":"identifier","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"lookup"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"], "},{"kind":"externalParam","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":119,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC6updateyyAA5PointVzF","interfaceLanguage":"swift"},"pathComponents":["Loader","update(_:)"],"names":{"title":"update(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"update"},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"point","declarationFragments":[{"kind":"identifier","spelling":"point"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"update"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"point"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":121,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC10modernOnlyyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","modernOnly()"],"names":{"title":"modernOnly()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"modernOnly"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"modernOnly"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":16,"minor":0}}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":124,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC11legacyFetchyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","legacyFetch()"],"names":{"title":"legacyFetch()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"legacyFetch"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"legacyFetch"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"*","message":"Use fetch(url:) instead","isUnconditionallyDeprecated":true}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":127,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC8oldFetchyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","oldFetch()"],"names":{"title":"oldFetch()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"oldFetch"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"oldFetch"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":15,"minor":0},"deprecated":{"major":17,"minor":0},"renamed":"fetch(url:)"}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":130,"character":16}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo16makeDefaultPointAA0E0VyF","interfaceLanguage":"swift"},"pathComponents":["makeDefaultPoint()"],"names":{"title":"makeDefaultPoint()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"makeDefaultPoint"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"makeDefaultPoint"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":133,"character":12}}},{"kind":{"identifier":"swift.var","displayName":"Global Variable"},"identifier":{"precise":"s:9SwiftDemo13defaultFlavorAA0D0Ovp","interfaceLanguage":"swift"},"pathComponents":["defaultFlavor"],"names":{"title":"defaultFlavor","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"defaultFlavor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Flavor","preciseIdentifier":"s:9SwiftDemo6FlavorO"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"defaultFlavor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Flavor","preciseIdentifier":"s:9SwiftDemo6FlavorO"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":134,"character":11}}},{"kind":{"identifier":"swift.var","displayName":"Global Variable"},"identifier":{"precise":"s:9SwiftDemo13globalCounterSivp","interfaceLanguage":"swift"},"pathComponents":["globalCounter"],"names":{"title":"globalCounter","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"globalCounter"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"globalCounter"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":135,"character":11}}},{"kind":{"identifier":"swift.typealias","displayName":"Type Alias"},"identifier":{"precise":"s:9SwiftDemo11Coordinatesa","interfaceLanguage":"swift"},"pathComponents":["Coordinates"],"names":{"title":"Coordinates","navigator":[{"kind":"identifier","spelling":"Coordinates"}],"subHeading":[{"kind":"keyword","spelling":"typealias"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Coordinates"}]},"declarationFragments":[{"kind":"keyword","spelling":"typealias"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Coordinates"},{"kind":"text","spelling":" = (latitude"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", longitude"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":136,"character":17}}}],"relationships":[{"kind":"requirementOf","source":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","target":"s:9SwiftDemo7GreeterP"},{"kind":"conformsTo","source":"s:9SwiftDemo0B0C","target":"s:9SwiftDemo7GreeterP"},{"kind":"memberOf","source":"s:9SwiftDemo0B0CACycfc","target":"s:9SwiftDemo0B0C"},{"kind":"memberOf","source":"s:9SwiftDemo0B0C5greet4nameS2S_tF","target":"s:9SwiftDemo0B0C","sourceOrigin":{"identifier":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","displayName":"Greeter.greet(name:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s23CustomStringConvertibleP","targetFallback":"Swift.CustomStringConvertible"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1xSdvp","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1ySdvp","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1x1yACSd_Sdtcfc","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp","displayName":"RawRepresentable.hashValue"}},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF","displayName":"RawRepresentable.hash(into:)"}},{"kind":"memberOf","source":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ","displayName":"Equatable.!=(_:_:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SQ","targetFallback":"Swift.Equatable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SH","targetFallback":"Swift.Hashable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SY","targetFallback":"Swift.RawRepresentable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s23CustomStringConvertibleP","targetFallback":"Swift.CustomStringConvertible"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO7vanillayA2CmF","target":"s:9SwiftDemo6FlavorO"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO9chocolateyA2CmF","target":"s:9SwiftDemo6FlavorO"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SY8rawValuexSg03RawB0Qz_tcfc","displayName":"RawRepresentable.init(rawValue:)"}},{"kind":"memberOf","source":"s:9SwiftDemo0B0C5greet4name5timesS2S_SitF","target":"s:9SwiftDemo0B0C"},{"kind":"memberOf","source":"s:9SwiftDemo0B0C7versionSSvpZ","target":"s:9SwiftDemo0B0C"},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s9EscapableP","targetFallback":"Swift.Escapable"},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s8CopyableP","targetFallback":"Swift.Copyable"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV11descriptionSSvp","target":"s:9SwiftDemo5PointV","sourceOrigin":{"identifier":"s:s23CustomStringConvertibleP11descriptionSSvp","displayName":"CustomStringConvertible.description"}},{"kind":"memberOf","source":"s:9SwiftDemo5PointV6lengthSdvp","target":"s:9SwiftDemo5PointV"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s9EscapableP","targetFallback":"Swift.Escapable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s8CopyableP","targetFallback":"Swift.Copyable"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO11descriptionSSvp","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:s23CustomStringConvertibleP11descriptionSSvp","displayName":"CustomStringConvertible.description"}},{"kind":"conformsTo","source":"s:9SwiftDemo5ShapeP","target":"s:9SwiftDemo7GreeterP"},{"kind":"requirementOf","source":"s:9SwiftDemo5ShapeP4areaSdvp","target":"s:9SwiftDemo5ShapeP"},{"kind":"requirementOf","source":"s:9SwiftDemo5ShapeP5sidesSivpZ","target":"s:9SwiftDemo5ShapeP"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4nameSSvp","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC11vertexCountSivp","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC6sharedACvpZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4nameACSgSS_tcfc","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale2byySd_tF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale2byySi_tF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4makeACyFZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC8describeySSACSgFZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonCyAA5PointVSicip","target":"s:9SwiftDemo7PolygonC"},{"kind":"conformsTo","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo5ShapeP"},{"kind":"conformsTo","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo7GreeterP"},{"kind":"inheritsFrom","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4sideSdvp","target":"s:9SwiftDemo6SquareC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4sideACSd_tcfc","target":"s:9SwiftDemo6SquareC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4areaSdvp","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo5ShapeP4areaSdvp","displayName":"Shape.area"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5sidesSivpZ","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo5ShapeP5sidesSivpZ","displayName":"Shape.sides"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5greet4nameS2S_tF","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","displayName":"Greeter.greet(name:)"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5scale2byySd_tF","target":"s:9SwiftDemo6SquareC"},{"kind":"overrides","source":"s:9SwiftDemo6SquareC5scale2byySd_tF","target":"s:9SwiftDemo7PolygonC5scale2byySd_tF"},{"kind":"memberOf","source":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO","target":"s:9SwiftDemo10ShapeErrorO","sourceOrigin":{"identifier":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp","displayName":"Error.localizedDescription"}},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s5ErrorP","targetFallback":"Swift.Error"},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s16SendableMetatypeP","targetFallback":"Swift.SendableMetatype"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO7unknownyA2CmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO6lengthyACSdcACmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4noneyA2CmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp","target":"s:9SwiftDemo11MeasurementO4UnitV"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc","target":"s:9SwiftDemo11MeasurementO4UnitV"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO6isNoneSbvp","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5innerAA5PointVvp","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5outerAA5PointVvp","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV6expand2byySd_tF","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV1poiyA2C_ACtFZ","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF","displayName":"Actor.withSerialExecutor(_:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF","displayName":"Actor.withSerialExecutor(_:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF","displayName":"Actor.preconditionIsolated(_:file:line:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF","displayName":"Actor.assertIsolated(_:file:line:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF","displayName":"Actor.assumeIsolated(_:file:line:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:ScA","targetFallback":"_Concurrency.Actor"},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:s16SendableMetatypeP","targetFallback":"Swift.SendableMetatype"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC5valueSivp","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterCACycfc","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC9incrementSiyF","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC5labelSSyF","target":"s:9SwiftDemo7CounterC"},{"kind":"conformsTo","source":"s:9SwiftDemo6CanvasC","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"memberOf","source":"s:9SwiftDemo6CanvasCACycfc","target":"s:9SwiftDemo6CanvasC"},{"kind":"memberOf","source":"s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF","target":"s:9SwiftDemo6CanvasC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderCACycfc","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4eachyyySiXEF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC6updateyyAA5PointVzF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC10modernOnlyyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC11legacyFetchyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC8oldFetchyyF","target":"s:9SwiftDemo6LoaderC"}]} \ No newline at end of file +{"metadata":{"formatVersion":{"major":0,"minor":6,"patch":0},"generator":"Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)"},"module":{"name":"SwiftDemo","platform":{"architecture":"arm64","environment":"simulator","vendor":"apple","operatingSystem":{"name":"ios","minimumVersion":{"major":15,"minor":0}}}},"symbols":[{"kind":{"identifier":"swift.protocol","displayName":"Protocol"},"identifier":{"precise":"s:9SwiftDemo7GreeterP","interfaceLanguage":"swift"},"pathComponents":["Greeter"],"names":{"title":"Greeter","navigator":[{"kind":"identifier","spelling":"Greeter"}],"subHeading":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Greeter"}]},"declarationFragments":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Greeter"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":0,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Greeter","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":1,"character":9}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo0B0C","interfaceLanguage":"swift"},"pathComponents":["Demo"],"names":{"title":"Demo","navigator":[{"kind":"identifier","spelling":"Demo"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Demo"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Demo"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":4,"character":13}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo0B0CACycfc","interfaceLanguage":"swift"},"pathComponents":["Demo","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":5,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo0B0C5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Demo","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":6,"character":16}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo5PointV","interfaceLanguage":"swift"},"pathComponents":["Point"],"names":{"title":"Point","navigator":[{"kind":"identifier","spelling":"Point"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Point"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Point"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":9,"character":14}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV1xSdvp","interfaceLanguage":"swift"},"pathComponents":["Point","x"],"names":{"title":"x","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":10,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV1ySdvp","interfaceLanguage":"swift"},"pathComponents":["Point","y"],"names":{"title":"y","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":11,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo5PointV1x1yACSd_Sdtcfc","interfaceLanguage":"swift"},"pathComponents":["Point","init(x:y:)"],"names":{"title":"init(x:y:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"x","declarationFragments":[{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},{"name":"y","declarationFragments":[{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":12,"character":11}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor"],"names":{"title":"Flavor","navigator":[{"kind":"identifier","spelling":"Flavor"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Flavor"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Flavor"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","hashValue"],"names":{"title":"hashValue","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","hash(into:)"],"names":{"title":"hash(into:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"into","internalName":"hasher","declarationFragments":[{"kind":"identifier","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftGenerics":{"constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO","interfaceLanguage":"swift"},"pathComponents":["Flavor","!=(_:_:)"],"names":{"title":"!=(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"docComment":{"module":"Swift","lines":[{"text":"Returns a Boolean value indicating whether two values are not equal."},{"text":""},{"text":"Inequality is the inverse of equality. For any values `a` and `b`, `a != b`"},{"text":"implies that `a == b` is `false`."},{"text":""},{"text":"This is the default implementation of the not-equal-to operator (`!=`)"},{"text":"for any type that conforms to `Equatable`."},{"text":""},{"text":"- Parameters:"},{"text":" - lhs: A value to compare."},{"text":" - rhs: Another value to compare."}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}],"accessLevel":"public"},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo6FlavorO7vanillayA2CmF","interfaceLanguage":"swift"},"pathComponents":["Flavor","vanilla"],"names":{"title":"Flavor.vanilla","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vanilla"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vanilla"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":31}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo6FlavorO9chocolateyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Flavor","chocolate"],"names":{"title":"Flavor.chocolate","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"chocolate"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"chocolate"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Demo.swift","position":{"line":15,"character":44}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc","interfaceLanguage":"swift"},"pathComponents":["Flavor","init(rawValue:)"],"names":{"title":"init(rawValue:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"rawValue","declarationFragments":[{"kind":"identifier","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo0B0C5greet4name5timesS2S_SitF","interfaceLanguage":"swift"},"pathComponents":["Demo","greet(name:times:)"],"names":{"title":"greet(name:times:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"times","declarationFragments":[{"kind":"identifier","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.class"},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"times"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":1,"character":16}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo0B0C7versionSSvpZ","interfaceLanguage":"swift"},"pathComponents":["Demo","version"],"names":{"title":"version","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"version"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.class"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"version"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":5,"character":22}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV11descriptionSSvp","interfaceLanguage":"swift"},"pathComponents":["Point","description"],"names":{"title":"description","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":9,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5PointV6lengthSdvp","interfaceLanguage":"swift"},"pathComponents":["Point","length"],"names":{"title":"length","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.struct"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":10,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6FlavorO11descriptionSSvp","interfaceLanguage":"swift"},"pathComponents":["Flavor","description"],"names":{"title":"description","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"swiftExtension":{"extendedModule":"SwiftDemo","typeKind":"swift.enum"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"description"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Extensions.swift","position":{"line":14,"character":15}}},{"kind":{"identifier":"swift.protocol","displayName":"Protocol"},"identifier":{"precise":"s:9SwiftDemo5ShapeP","interfaceLanguage":"swift"},"pathComponents":["Shape"],"names":{"title":"Shape","navigator":[{"kind":"identifier","spelling":"Shape"}],"subHeading":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Shape"}]},"declarationFragments":[{"kind":"keyword","spelling":"protocol"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Shape"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Greeter","preciseIdentifier":"s:9SwiftDemo7GreeterP"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":2,"character":16}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo5ShapeP4areaSdvp","interfaceLanguage":"swift"},"pathComponents":["Shape","area"],"names":{"title":"area","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":3,"character":8}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo5ShapeP5sidesSivpZ","interfaceLanguage":"swift"},"pathComponents":["Shape","sides"],"names":{"title":"sides","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":4,"character":15}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7PolygonC","interfaceLanguage":"swift"},"pathComponents":["Polygon"],"names":{"title":"Polygon","navigator":[{"kind":"identifier","spelling":"Polygon"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Polygon"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Polygon"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":7,"character":11}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4nameSSvp","interfaceLanguage":"swift"},"pathComponents":["Polygon","name"],"names":{"title":"name","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":8,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC11vertexCountSivp","interfaceLanguage":"swift"},"pathComponents":["Polygon","vertexCount"],"names":{"title":"vertexCount","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":9,"character":28}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo7PolygonC6sharedACvpZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","shared"],"names":{"title":"shared","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shared"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shared"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":10,"character":22}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc","interfaceLanguage":"swift"},"pathComponents":["Polygon","init(name:vertexCount:)"],"names":{"title":"init(name:vertexCount:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"vertexCount","declarationFragments":[{"kind":"identifier","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"vertexCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":12,"character":11}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4nameACSgSS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Polygon","init(name:)"],"names":{"title":"init(name:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"convenience"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":17,"character":23}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":22,"character":14}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale2byySi_tF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"open","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":23,"character":14}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF","interfaceLanguage":"swift"},"pathComponents":["Polygon","scale(x:y:)"],"names":{"title":"scale(x:y:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"x","declarationFragments":[{"kind":"identifier","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},{"name":"y","declarationFragments":[{"kind":"identifier","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"x"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"y"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":24,"character":16}}},{"kind":{"identifier":"swift.type.method","displayName":"Type Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC4makeACyFZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","make()"],"names":{"title":"make()","subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"make"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}]},"declarationFragments":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"make"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":26,"character":22}}},{"kind":{"identifier":"swift.type.method","displayName":"Type Method"},"identifier":{"precise":"s:9SwiftDemo7PolygonC8describeySSACSgFZ","interfaceLanguage":"swift"},"pathComponents":["Polygon","describe(_:)"],"names":{"title":"describe(_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"describe"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"polygon","declarationFragments":[{"kind":"identifier","spelling":"polygon"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"describe"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"polygon"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Polygon","preciseIdentifier":"s:9SwiftDemo7PolygonC"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":27,"character":23}}},{"kind":{"identifier":"swift.subscript","displayName":"Instance Subscript"},"identifier":{"precise":"s:9SwiftDemo7PolygonCyAA5PointVSicip","interfaceLanguage":"swift"},"pathComponents":["Polygon","subscript(_:)"],"names":{"title":"subscript(_:)","subHeading":[{"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"parameters":[{"name":"index","declarationFragments":[{"kind":"identifier","spelling":"index"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"subscript"},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"index"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":29,"character":11}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6SquareC","interfaceLanguage":"swift"},"pathComponents":["Square"],"names":{"title":"Square","navigator":[{"kind":"identifier","spelling":"Square"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Square"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Square"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":34,"character":19}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC4sideSdvp","interfaceLanguage":"swift"},"pathComponents":["Square","side"],"names":{"title":"side","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":35,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6SquareC4sideACSd_tcfc","interfaceLanguage":"swift"},"pathComponents":["Square","init(side:)"],"names":{"title":"init(side:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"side","declarationFragments":[{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":37,"character":11}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC4areaSdvp","interfaceLanguage":"swift"},"pathComponents":["Square","area"],"names":{"title":"area","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":42,"character":15}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo6SquareC5sidesSivpZ","interfaceLanguage":"swift"},"pathComponents":["Square","sides"],"names":{"title":"sides","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"sides"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":43,"character":22}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6SquareC5greet4nameS2S_tF","interfaceLanguage":"swift"},"pathComponents":["Square","greet(name:)"],"names":{"title":"greet(name:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"greet"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":44,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6SquareC5scale2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Square","scale(by:)"],"names":{"title":"scale(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"factor","declarationFragments":[{"kind":"identifier","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"override"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"scale"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"factor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":46,"character":25}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo13PrecipitationO","interfaceLanguage":"swift"},"pathComponents":["Precipitation"],"names":{"title":"Precipitation","navigator":[{"kind":"identifier","spelling":"Precipitation"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Precipitation"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Precipitation"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":50,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO","interfaceLanguage":"swift"},"pathComponents":["Precipitation","hashValue"],"names":{"title":"hashValue","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hashValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public"},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo13PrecipitationO","interfaceLanguage":"swift"},"pathComponents":["Precipitation","hash(into:)"],"names":{"title":"hash(into:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"into","internalName":"hasher","declarationFragments":[{"kind":"identifier","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftGenerics":{"constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol","constraints":[{"kind":"conformance","lhs":"Self","rhs":"Hashable","rhsPrecise":"s:SH"},{"kind":"conformance","lhs":"Self.RawValue","rhs":"Hashable","rhsPrecise":"s:SH"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"hash"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"into"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"hasher"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Hasher","preciseIdentifier":"s:s6HasherV"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo13PrecipitationO","interfaceLanguage":"swift"},"pathComponents":["Precipitation","!=(_:_:)"],"names":{"title":"!=(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"docComment":{"module":"Swift","lines":[{"text":"Returns a Boolean value indicating whether two values are not equal."},{"text":""},{"text":"Inequality is the inverse of equality. For any values `a` and `b`, `a != b`"},{"text":"implies that `a == b` is `false`."},{"text":""},{"text":"This is the default implementation of the not-equal-to operator (`!=`)"},{"text":"for any type that conforms to `Equatable`."},{"text":""},{"text":"- Parameters:"},{"text":" - lhs: A value to compare."},{"text":" - rhs: Another value to compare."}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Self"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"!="},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"borrowing"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}],"accessLevel":"public"},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo13PrecipitationO4rainyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Precipitation","rain"],"names":{"title":"Precipitation.rain","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"rain"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"rain"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":51,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo13PrecipitationO4snowyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Precipitation","snow"],"names":{"title":"Precipitation.snow","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"snow"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"snow"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":51,"character":15}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo13PrecipitationO4noneyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Precipitation","none"],"names":{"title":"Precipitation.none","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":51,"character":21}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Precipitation","init(rawValue:)"],"names":{"title":"init(rawValue:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"rawValue","declarationFragments":[{"kind":"identifier","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"?("},{"kind":"externalParam","spelling":"rawValue"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public"},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO","interfaceLanguage":"swift"},"pathComponents":["ShapeError"],"names":{"title":"ShapeError","navigator":[{"kind":"identifier","spelling":"ShapeError"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"ShapeError"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"ShapeError"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":54,"character":12}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO","interfaceLanguage":"swift"},"pathComponents":["ShapeError","localizedDescription"],"names":{"title":"localizedDescription","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"localizedDescription"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"docComment":{"module":"Foundation","lines":[{"text":"Retrieve the localized description for this error."}]},"swiftExtension":{"extendedModule":"Swift","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"localizedDescription"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":8,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":10}},{"domain":"tvOS","introduced":{"major":9,"minor":0}},{"domain":"watchOS","introduced":{"major":2,"minor":0}}]},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","invalidSide(_:)"],"names":{"title":"ShapeError.invalidSide(_:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"invalidSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"invalidSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":55,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","tooManySides(count:limit:)"],"names":{"title":"ShapeError.tooManySides(count:limit:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"tooManySides"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"count"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"limit"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"tooManySides"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"count"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"limit"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":56,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo10ShapeErrorO7unknownyA2CmF","interfaceLanguage":"swift"},"pathComponents":["ShapeError","unknown"],"names":{"title":"ShapeError.unknown","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"unknown"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"unknown"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":57,"character":9}}},{"kind":{"identifier":"swift.enum","displayName":"Enumeration"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO","interfaceLanguage":"swift"},"pathComponents":["Measurement"],"names":{"title":"Measurement","navigator":[{"kind":"identifier","spelling":"Measurement"}],"subHeading":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Measurement"}]},"declarationFragments":[{"kind":"keyword","spelling":"enum"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Measurement"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":60,"character":12}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO6lengthyACSdcACmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","length(_:)"],"names":{"title":"Measurement.length(_:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"length"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":61,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","area(width:height:)"],"names":{"title":"Measurement.area(width:height:)","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"width"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"height"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"area"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"width"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"height"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":62,"character":9}}},{"kind":{"identifier":"swift.enum.case","displayName":"Case"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4noneyA2CmF","interfaceLanguage":"swift"},"pathComponents":["Measurement","none"],"names":{"title":"Measurement.none","subHeading":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}]},"declarationFragments":[{"kind":"keyword","spelling":"case"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"none"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":63,"character":9}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit"],"names":{"title":"Measurement.Unit","navigator":[{"kind":"identifier","spelling":"Unit"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Unit"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Unit"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":65,"character":18}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit","symbol"],"names":{"title":"symbol","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":66,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc","interfaceLanguage":"swift"},"pathComponents":["Measurement","Unit","init(symbol:)"],"names":{"title":"init(symbol:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"symbol","declarationFragments":[{"kind":"identifier","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"symbol"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":67,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo11MeasurementO6isNoneSbvp","interfaceLanguage":"swift"},"pathComponents":["Measurement","isNone"],"names":{"title":"isNone","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"isNone"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"isNone"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Bool","preciseIdentifier":"s:Sb"},{"kind":"text","spelling":" { "},{"kind":"keyword","spelling":"get"},{"kind":"text","spelling":" }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":70,"character":15}}},{"kind":{"identifier":"swift.struct","displayName":"Structure"},"identifier":{"precise":"s:9SwiftDemo4RingV","interfaceLanguage":"swift"},"pathComponents":["Ring"],"names":{"title":"Ring","navigator":[{"kind":"identifier","spelling":"Ring"}],"subHeading":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Ring"}]},"declarationFragments":[{"kind":"keyword","spelling":"struct"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Ring"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":76,"character":14}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo4RingV5innerAA5PointVvp","interfaceLanguage":"swift"},"pathComponents":["Ring","inner"],"names":{"title":"inner","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":77,"character":15}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo4RingV5outerAA5PointVvp","interfaceLanguage":"swift"},"pathComponents":["Ring","outer"],"names":{"title":"outer","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":78,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc","interfaceLanguage":"swift"},"pathComponents":["Ring","init(inner:outer:)"],"names":{"title":"init(inner:outer:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"inner","declarationFragments":[{"kind":"identifier","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},{"name":"outer","declarationFragments":[{"kind":"identifier","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"inner"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"outer"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":80,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo4RingV6expand2byySd_tF","interfaceLanguage":"swift"},"pathComponents":["Ring","expand(by:)"],"names":{"title":"expand(by:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"expand"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"by","internalName":"delta","declarationFragments":[{"kind":"identifier","spelling":"delta"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"mutating"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"expand"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"by"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"delta"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":85,"character":25}}},{"kind":{"identifier":"swift.func.op","displayName":"Operator"},"identifier":{"precise":"s:9SwiftDemo4RingV1poiyA2C_ACtFZ","interfaceLanguage":"swift"},"pathComponents":["Ring","+(_:_:)"],"names":{"title":"+(_:_:)","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"+"},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},"functionSignature":{"parameters":[{"name":"lhs","declarationFragments":[{"kind":"identifier","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},{"name":"rhs","declarationFragments":[{"kind":"identifier","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"+"},{"kind":"text","spelling":" "},{"kind":"text","spelling":"("},{"kind":"internalParam","spelling":"lhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":", "},{"kind":"internalParam","spelling":"rhs"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Ring","preciseIdentifier":"s:9SwiftDemo4RingV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":90,"character":23}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter"],"names":{"title":"Counter","navigator":[{"kind":"identifier","spelling":"Counter"}],"subHeading":[{"kind":"keyword","spelling":"actor"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Counter"}]},"declarationFragments":[{"kind":"keyword","spelling":"actor"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Counter"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":95,"character":13}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","withSerialExecutor(_:)"],"names":{"title":"withSerialExecutor(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">((any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Perform an operation with the actor's ``SerialExecutor``."},{"text":""},{"text":"This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while"},{"text":"retaining the actor for the duration of the operation. This is to ensure the lifetime"},{"text":"of the executor while performing the operation."}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1},{"name":"E","index":1,"depth":1}],"constraints":[{"kind":"conformance","lhs":"E","rhs":"Error","rhsPrecise":"s:s5ErrorP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Error","preciseIdentifier":"s:s5ErrorP"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : ~Copyable"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","withSerialExecutor(_:)"],"names":{"title":"withSerialExecutor(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"keyword","spelling":"nonisolated(nonsending)"},{"kind":"text","spelling":" (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Perform an operation with the actor's ``SerialExecutor``."},{"text":""},{"text":"This converts the actor's ``Actor/unownedExecutor`` to a ``SerialExecutor`` while"},{"text":"retaining the actor for the duration of the operation. This is to ensure the lifetime"},{"text":"of the executor while performing the operation."}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1},{"name":"E","index":1,"depth":1}],"constraints":[{"kind":"conformance","lhs":"E","rhs":"Error","rhsPrecise":"s:s5ErrorP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withSerialExecutor"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"genericParameter","spelling":"E"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"nonisolated(nonsending)"},{"kind":"text","spelling":" (any "},{"kind":"typeIdentifier","spelling":"SerialExecutor","preciseIdentifier":"s:Scf"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"E"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Error","preciseIdentifier":"s:s5ErrorP"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : ~Copyable"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","preconditionIsolated(_:file:line:)"],"names":{"title":"preconditionIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"preconditionIsolated"},{"kind":"text","spelling":"("},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":")"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Stops program execution if the current task is not executing on this"},{"text":"actor's serial executor."},{"text":""},{"text":"This function's effect varies depending on the build flag used:"},{"text":""},{"text":"* In playgrounds and `-Onone` builds (the default for Xcode's Debug"},{"text":" configuration), stops program execution in a debuggable state after"},{"text":" printing `message`."},{"text":""},{"text":"* In `-O` builds (the default for Xcode's Release configuration), stops"},{"text":" program execution."},{"text":""},{"text":"- Note: Because this check is performed against the actor's serial executor,"},{"text":" if another actor uses the same serial executor--by using"},{"text":" that actor's serial executor as its own ``Actor/unownedExecutor``--this"},{"text":" check will succeed. From a concurrency safety perspective, the"},{"text":" serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - message: The message to print if the assertion fails."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."}]},"functionSignature":{"parameters":[{"name":"message","declarationFragments":[{"kind":"identifier","spelling":"message"},{"kind":"text","spelling":": () -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"text","spelling":"@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\n"},{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"preconditionIsolated"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"message"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" = String(), "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":")"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","assertIsolated(_:file:line:)"],"names":{"title":"assertIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assertIsolated"},{"kind":"text","spelling":"("},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":")"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Stops program execution if the current task is not executing on this"},{"text":"actor's serial executor."},{"text":""},{"text":"This function's effect varies depending on the build flag used:"},{"text":""},{"text":"* In playgrounds and `-Onone` builds (the default for Xcode's Debug"},{"text":" configuration), stops program execution in a debuggable state after"},{"text":" printing `message`."},{"text":""},{"text":"* In `-O` builds (the default for Xcode's Release configuration),"},{"text":" the isolation check is not performed and there are no effects."},{"text":""},{"text":"- Note: This check is performed against the actor's serial executor,"},{"text":" meaning that / if another actor uses the same serial executor--by using"},{"text":" that actor's serial executor as its own ``Actor/unownedExecutor``--this"},{"text":" check will succeed , as from a concurrency safety perspective, the"},{"text":" serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - message: The message to print if the assertion fails."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."}]},"functionSignature":{"parameters":[{"name":"message","declarationFragments":[{"kind":"identifier","spelling":"message"},{"kind":"text","spelling":": () -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"text","spelling":"()"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"text","spelling":"@backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)\n"},{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assertIsolated"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"message"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@autoclosure "},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" = String(), "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":")"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC","interfaceLanguage":"swift"},"pathComponents":["Counter","assumeIsolated(_:file:line:)"],"names":{"title":"assumeIsolated(_:file:line:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assumeIsolated"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">(("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"rethrows"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"}]},"docComment":{"module":"_Concurrency","lines":[{"text":"Assume that the current task is executing on this actor's serial executor,"},{"text":"or stop program execution otherwise."},{"text":""},{"text":"You call this method to *assume and verify* that the currently"},{"text":"executing synchronous function is actually executing on the serial"},{"text":"executor of this actor."},{"text":""},{"text":"If that is the case, the operation is invoked with an `isolated` version"},{"text":"of the actor, allowing synchronous access to actor local state without"},{"text":"hopping through asynchronous boundaries."},{"text":""},{"text":"If the current context is not running on the actor's serial executor, or"},{"text":"if the actor is a reference to a remote actor, this method will crash"},{"text":"with a fatal error (similar to ``preconditionIsolated(_:file:line:)``)."},{"text":""},{"text":"Note that this check is performed against the passed in actor's serial"},{"text":"executor, meaning that if another actor uses the same serial executor--by"},{"text":"using that actor's ``Actor/unownedExecutor`` as its own"},{"text":"``Actor/unownedExecutor``--this check will succeed, as from a concurrency"},{"text":"safety perspective, the serial executor guarantees mutual exclusion of"},{"text":"those two actors."},{"text":""},{"text":"This method can only be used from synchronous functions, as asynchronous"},{"text":"functions should instead perform a normal method call to the actor, which"},{"text":"will hop task execution to the target actor if necessary."},{"text":""},{"text":"- Note: This check is performed against the actor's serial executor,"},{"text":" meaning that / if another actor uses the same serial executor--by using"},{"text":" another actor's executor as its own ``Actor/unownedExecutor``"},{"text":" --this check will succeed , as from a concurrency safety perspective,"},{"text":" the serial executor guarantees mutual exclusion of those two actors."},{"text":""},{"text":"- Parameters:"},{"text":" - operation: the operation that will be executed if the current context"},{"text":" is executing on the actors serial executor."},{"text":" - file: The file name to print if the assertion fails. The default is"},{"text":" where this method was called."},{"text":" - line: The line number to print if the assertion fails The default is"},{"text":" where this method was called."},{"text":"- Returns: the return value of the `operation`"},{"text":"- Throws: rethrows the `Error` thrown by the operation if it threw"}]},"functionSignature":{"parameters":[{"name":"operation","declarationFragments":[{"kind":"identifier","spelling":"operation"},{"kind":"text","spelling":": ("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"}]},{"name":"file","declarationFragments":[{"kind":"identifier","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"}]},{"name":"line","declarationFragments":[{"kind":"identifier","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":1}],"constraints":[{"kind":"conformance","lhs":"T","rhs":"Sendable","rhsPrecise":"s:s8SendableP"}]},"swiftExtension":{"extendedModule":"_Concurrency","typeKind":"swift.protocol"},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"assumeIsolated"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"operation"},{"kind":"text","spelling":": ("},{"kind":"keyword","spelling":"isolated"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Self"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"file"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"StaticString","preciseIdentifier":"s:s12StaticStringV"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#fileID"},{"kind":"text","spelling":", "},{"kind":"externalParam","spelling":"line"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt","preciseIdentifier":"s:Su"},{"kind":"text","spelling":" = "},{"kind":"keyword","spelling":"#line"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"rethrows"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Sendable","preciseIdentifier":"s:s8SendableP"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":13,"minor":0}},{"domain":"macOS","introduced":{"major":10,"minor":15}},{"domain":"tvOS","introduced":{"major":13,"minor":0}},{"domain":"watchOS","introduced":{"major":6,"minor":0}}]},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7CounterC5valueSivp","interfaceLanguage":"swift"},"pathComponents":["Counter","value"],"names":{"title":"value","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":96,"character":28}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7CounterCACycfc","interfaceLanguage":"swift"},"pathComponents":["Counter","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":97,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7CounterC9incrementSiyF","interfaceLanguage":"swift"},"pathComponents":["Counter","increment()"],"names":{"title":"increment()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"increment"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"increment"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":98,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7CounterC5labelSSyF","interfaceLanguage":"swift"},"pathComponents":["Counter","label()"],"names":{"title":"label()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"label"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"attribute","spelling":"nonisolated"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"label"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":102,"character":28}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6CanvasC","interfaceLanguage":"swift"},"pathComponents":["Canvas"],"names":{"title":"Canvas","navigator":[{"kind":"identifier","spelling":"Canvas"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Canvas"}]},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Canvas"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":106,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6CanvasCACycfc","interfaceLanguage":"swift"},"pathComponents":["Canvas","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":107,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF","interfaceLanguage":"swift"},"pathComponents":["Canvas","draw(_:)"],"names":{"title":"draw(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"draw"},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"shape","declarationFragments":[{"kind":"identifier","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"attribute","spelling":"@"},{"kind":"attribute","spelling":"MainActor","preciseIdentifier":"s:ScM"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"draw"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"any"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":108,"character":16}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo6LoaderC","interfaceLanguage":"swift"},"pathComponents":["Loader"],"names":{"title":"Loader","navigator":[{"kind":"identifier","spelling":"Loader"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Loader"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Loader"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":111,"character":19}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo6LoaderCACycfc","interfaceLanguage":"swift"},"pathComponents":["Loader","init()"],"names":{"title":"init()","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}]},"functionSignature":{},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"()"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":112,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF","interfaceLanguage":"swift"},"pathComponents":["Loader","load(path:)"],"names":{"title":"load(path:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}]},"functionSignature":{"parameters":[{"name":"path","declarationFragments":[{"kind":"identifier","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"load"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"path"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Data","preciseIdentifier":"s:10Foundation4DataV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":114,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF","interfaceLanguage":"swift"},"pathComponents":["Loader","fetch(url:)"],"names":{"title":"fetch(url:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"fetch"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"functionSignature":{"parameters":[{"name":"url","declarationFragments":[{"kind":"identifier","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"fetch"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"url"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"URL","preciseIdentifier":"s:10Foundation3URLV"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":115,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF","interfaceLanguage":"swift"},"pathComponents":["Loader","wait(seconds:)"],"names":{"title":"wait(seconds:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"wait"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"}]},"functionSignature":{"parameters":[{"name":"seconds","declarationFragments":[{"kind":"identifier","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"wait"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"seconds"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"async"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":116,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF","interfaceLanguage":"swift"},"pathComponents":["Loader","transform(_:)"],"names":{"title":"transform(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"transform"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"}]},"functionSignature":{"parameters":[{"name":"shape","declarationFragments":[{"kind":"identifier","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"}]}],"returns":[{"kind":"typeIdentifier","spelling":"T"}]},"swiftGenerics":{"parameters":[{"name":"T","index":0,"depth":0}],"constraints":[{"kind":"conformance","lhs":"T","rhs":"Shape","rhsPrecise":"s:9SwiftDemo5ShapeP"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"transform"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"T"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"shape"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"T","preciseIdentifier":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF1TL_xmfp"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"where"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"T"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Shape","preciseIdentifier":"s:9SwiftDemo5ShapeP"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":118,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF","interfaceLanguage":"swift"},"pathComponents":["Loader","first(of:)"],"names":{"title":"first(of:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"first"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"Element"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"of"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]) -> "},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"of","internalName":"items","declarationFragments":[{"kind":"identifier","spelling":"items"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Element"},{"kind":"text","spelling":"?"}]},"swiftGenerics":{"parameters":[{"name":"Element","index":0,"depth":0}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"first"},{"kind":"text","spelling":"<"},{"kind":"genericParameter","spelling":"Element"},{"kind":"text","spelling":">("},{"kind":"externalParam","spelling":"of"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"items"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"]) -> "},{"kind":"typeIdentifier","spelling":"Element","preciseIdentifier":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF7ElementL_xmfp"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":119,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF","interfaceLanguage":"swift"},"pathComponents":["Loader","withCompletion(_:)"],"names":{"title":"withCompletion(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withCompletion"},{"kind":"text","spelling":"(("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"completion","declarationFragments":[{"kind":"identifier","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" ("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"withCompletion"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"completion"},{"kind":"text","spelling":": "},{"kind":"attribute","spelling":"@escaping"},{"kind":"text","spelling":" ("},{"kind":"typeIdentifier","spelling":"Result","preciseIdentifier":"s:s6ResultO"},{"kind":"text","spelling":"<"},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":", "},{"kind":"typeIdentifier","spelling":"ShapeError","preciseIdentifier":"s:9SwiftDemo10ShapeErrorO"},{"kind":"text","spelling":">) -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":121,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC4eachyyySiXEF","interfaceLanguage":"swift"},"pathComponents":["Loader","each(_:)"],"names":{"title":"each(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"each"},{"kind":"text","spelling":"(("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"body","declarationFragments":[{"kind":"identifier","spelling":"body"},{"kind":"text","spelling":": ("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"each"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"body"},{"kind":"text","spelling":": ("},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Void","preciseIdentifier":"s:s4Voida"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":122,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF","interfaceLanguage":"swift"},"pathComponents":["Loader","lookup(table:key:)"],"names":{"title":"lookup(table:key:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"lookup"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"], "},{"kind":"externalParam","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"table","declarationFragments":[{"kind":"identifier","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"]"}]},{"name":"key","declarationFragments":[{"kind":"identifier","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"lookup"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"table"},{"kind":"text","spelling":": ["},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":" : "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"], "},{"kind":"externalParam","spelling":"key"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":124,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC6updateyyAA5PointVzF","interfaceLanguage":"swift"},"pathComponents":["Loader","update(_:)"],"names":{"title":"update(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"update"},{"kind":"text","spelling":"("},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"point","declarationFragments":[{"kind":"identifier","spelling":"point"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]}],"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"update"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"point"},{"kind":"text","spelling":": "},{"kind":"keyword","spelling":"inout"},{"kind":"text","spelling":" "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":126,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC10modernOnlyyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","modernOnly()"],"names":{"title":"modernOnly()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"modernOnly"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"modernOnly"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":16,"minor":0}}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":129,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC11legacyFetchyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","legacyFetch()"],"names":{"title":"legacyFetch()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"legacyFetch"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"legacyFetch"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"*","message":"Use fetch(url:) instead","isUnconditionallyDeprecated":true}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":132,"character":16}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo6LoaderC8oldFetchyyF","interfaceLanguage":"swift"},"pathComponents":["Loader","oldFetch()"],"names":{"title":"oldFetch()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"oldFetch"},{"kind":"text","spelling":"()"}]},"functionSignature":{"returns":[{"kind":"text","spelling":"()"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"oldFetch"},{"kind":"text","spelling":"()"}],"accessLevel":"public","availability":[{"domain":"iOS","introduced":{"major":15,"minor":0},"deprecated":{"major":17,"minor":0},"renamed":"fetch(url:)"}],"location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":135,"character":16}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo16makeDefaultPointAA0E0VyF","interfaceLanguage":"swift"},"pathComponents":["makeDefaultPoint()"],"names":{"title":"makeDefaultPoint()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"makeDefaultPoint"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"makeDefaultPoint"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Point","preciseIdentifier":"s:9SwiftDemo5PointV"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":138,"character":12}}},{"kind":{"identifier":"swift.var","displayName":"Global Variable"},"identifier":{"precise":"s:9SwiftDemo13defaultFlavorAA0D0Ovp","interfaceLanguage":"swift"},"pathComponents":["defaultFlavor"],"names":{"title":"defaultFlavor","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"defaultFlavor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Flavor","preciseIdentifier":"s:9SwiftDemo6FlavorO"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"defaultFlavor"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Flavor","preciseIdentifier":"s:9SwiftDemo6FlavorO"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":139,"character":11}}},{"kind":{"identifier":"swift.var","displayName":"Global Variable"},"identifier":{"precise":"s:9SwiftDemo13globalCounterSivp","interfaceLanguage":"swift"},"pathComponents":["globalCounter"],"names":{"title":"globalCounter","subHeading":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"globalCounter"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"globalCounter"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":140,"character":11}}},{"kind":{"identifier":"swift.typealias","displayName":"Type Alias"},"identifier":{"precise":"s:9SwiftDemo11Coordinatesa","interfaceLanguage":"swift"},"pathComponents":["Coordinates"],"names":{"title":"Coordinates","navigator":[{"kind":"identifier","spelling":"Coordinates"}],"subHeading":[{"kind":"keyword","spelling":"typealias"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Coordinates"}]},"declarationFragments":[{"kind":"keyword","spelling":"typealias"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Coordinates"},{"kind":"text","spelling":" = (latitude"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":", longitude"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Shapes.swift","position":{"line":141,"character":17}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo11checkedSideyS2dKF","interfaceLanguage":"swift"},"pathComponents":["checkedSide(_:)"],"names":{"title":"checkedSide(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"checkedSide"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"functionSignature":{"parameters":[{"name":"side","declarationFragments":[{"kind":"identifier","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"checkedSide"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"side"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"},{"kind":"text","spelling":") "},{"kind":"keyword","spelling":"throws"},{"kind":"text","spelling":" -> "},{"kind":"typeIdentifier","spelling":"Double","preciseIdentifier":"s:Sd"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":3,"character":12}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo8echoInt8ys0D0VADF","interfaceLanguage":"swift"},"pathComponents":["echoInt8(_:)"],"names":{"title":"echoInt8(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"echoInt8"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"Int8","preciseIdentifier":"s:s4Int8V"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int8","preciseIdentifier":"s:s4Int8V"}]},"functionSignature":{"parameters":[{"name":"value","declarationFragments":[{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int8","preciseIdentifier":"s:s4Int8V"}]}],"returns":[{"kind":"typeIdentifier","spelling":"Int8","preciseIdentifier":"s:s4Int8V"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"echoInt8"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int8","preciseIdentifier":"s:s4Int8V"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"Int8","preciseIdentifier":"s:s4Int8V"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":8,"character":12}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo10echoUInt64ys0D0VADF","interfaceLanguage":"swift"},"pathComponents":["echoUInt64(_:)"],"names":{"title":"echoUInt64(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"echoUInt64"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"UInt64","preciseIdentifier":"s:s6UInt64V"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"UInt64","preciseIdentifier":"s:s6UInt64V"}]},"functionSignature":{"parameters":[{"name":"value","declarationFragments":[{"kind":"identifier","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt64","preciseIdentifier":"s:s6UInt64V"}]}],"returns":[{"kind":"typeIdentifier","spelling":"UInt64","preciseIdentifier":"s:s6UInt64V"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"echoUInt64"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"value"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"UInt64","preciseIdentifier":"s:s6UInt64V"},{"kind":"text","spelling":") -> "},{"kind":"typeIdentifier","spelling":"UInt64","preciseIdentifier":"s:s6UInt64V"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":9,"character":12}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo10largestIntSiyF","interfaceLanguage":"swift"},"pathComponents":["largestInt()"],"names":{"title":"largestInt()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"largestInt"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"largestInt"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":10,"character":12}}},{"kind":{"identifier":"swift.func","displayName":"Function"},"identifier":{"precise":"s:9SwiftDemo5shoutySSSgACF","interfaceLanguage":"swift"},"pathComponents":["shout(_:)"],"names":{"title":"shout(_:)","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shout"},{"kind":"text","spelling":"("},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":"?"}]},"functionSignature":{"parameters":[{"name":"name","declarationFragments":[{"kind":"identifier","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":"?"}]}],"returns":[{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":"?"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"shout"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"_"},{"kind":"text","spelling":" "},{"kind":"internalParam","spelling":"name"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":"?) -> "},{"kind":"typeIdentifier","spelling":"String","preciseIdentifier":"s:SS"},{"kind":"text","spelling":"?"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":11,"character":12}}},{"kind":{"identifier":"swift.class","displayName":"Class"},"identifier":{"precise":"s:9SwiftDemo7TrackerC","interfaceLanguage":"swift"},"pathComponents":["Tracker"],"names":{"title":"Tracker","navigator":[{"kind":"identifier","spelling":"Tracker"}],"subHeading":[{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Tracker"}]},"declarationFragments":[{"kind":"keyword","spelling":"final"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"class"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"Tracker"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":13,"character":19}}},{"kind":{"identifier":"swift.type.property","displayName":"Type Property"},"identifier":{"precise":"s:9SwiftDemo7TrackerC9liveCountSivpZ","interfaceLanguage":"swift"},"pathComponents":["Tracker","liveCount"],"names":{"title":"liveCount","subHeading":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"liveCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"static"},{"kind":"text","spelling":" "},{"kind":"keyword","spelling":"var"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"liveCount"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":" { get }"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":14,"character":35}}},{"kind":{"identifier":"swift.property","displayName":"Instance Property"},"identifier":{"precise":"s:9SwiftDemo7TrackerC2idSivp","interfaceLanguage":"swift"},"pathComponents":["Tracker","id"],"names":{"title":"id","subHeading":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"id"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]},"declarationFragments":[{"kind":"keyword","spelling":"let"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"id"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":15,"character":15}}},{"kind":{"identifier":"swift.init","displayName":"Initializer"},"identifier":{"precise":"s:9SwiftDemo7TrackerC2idACSi_tcfc","interfaceLanguage":"swift"},"pathComponents":["Tracker","init(id:)"],"names":{"title":"init(id:)","subHeading":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"id"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}]},"functionSignature":{"parameters":[{"name":"id","declarationFragments":[{"kind":"identifier","spelling":"id"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"}]}]},"declarationFragments":[{"kind":"keyword","spelling":"init"},{"kind":"text","spelling":"("},{"kind":"externalParam","spelling":"id"},{"kind":"text","spelling":": "},{"kind":"typeIdentifier","spelling":"Int","preciseIdentifier":"s:Si"},{"kind":"text","spelling":")"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":17,"character":11}}},{"kind":{"identifier":"swift.method","displayName":"Instance Method"},"identifier":{"precise":"s:9SwiftDemo7TrackerC4sameACyF","interfaceLanguage":"swift"},"pathComponents":["Tracker","same()"],"names":{"title":"same()","subHeading":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"same"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Tracker","preciseIdentifier":"s:9SwiftDemo7TrackerC"}]},"functionSignature":{"returns":[{"kind":"typeIdentifier","spelling":"Tracker","preciseIdentifier":"s:9SwiftDemo7TrackerC"}]},"declarationFragments":[{"kind":"keyword","spelling":"func"},{"kind":"text","spelling":" "},{"kind":"identifier","spelling":"same"},{"kind":"text","spelling":"() -> "},{"kind":"typeIdentifier","spelling":"Tracker","preciseIdentifier":"s:9SwiftDemo7TrackerC"}],"accessLevel":"public","location":{"uri":"file://Sources/SwiftDemo/Values.swift","position":{"line":24,"character":16}}}],"relationships":[{"kind":"requirementOf","source":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","target":"s:9SwiftDemo7GreeterP"},{"kind":"conformsTo","source":"s:9SwiftDemo0B0C","target":"s:9SwiftDemo7GreeterP"},{"kind":"memberOf","source":"s:9SwiftDemo0B0CACycfc","target":"s:9SwiftDemo0B0C"},{"kind":"memberOf","source":"s:9SwiftDemo0B0C5greet4nameS2S_tF","target":"s:9SwiftDemo0B0C","sourceOrigin":{"identifier":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","displayName":"Greeter.greet(name:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s23CustomStringConvertibleP","targetFallback":"Swift.CustomStringConvertible"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1xSdvp","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1ySdvp","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV1x1yACSd_Sdtcfc","target":"s:9SwiftDemo5PointV"},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp","displayName":"RawRepresentable.hashValue"}},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF","displayName":"RawRepresentable.hash(into:)"}},{"kind":"memberOf","source":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ","displayName":"Equatable.!=(_:_:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SQ","targetFallback":"Swift.Equatable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SH","targetFallback":"Swift.Hashable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:SY","targetFallback":"Swift.RawRepresentable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s23CustomStringConvertibleP","targetFallback":"Swift.CustomStringConvertible"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO7vanillayA2CmF","target":"s:9SwiftDemo6FlavorO"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO9chocolateyA2CmF","target":"s:9SwiftDemo6FlavorO"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:SY8rawValuexSg03RawB0Qz_tcfc","displayName":"RawRepresentable.init(rawValue:)"}},{"kind":"memberOf","source":"s:9SwiftDemo0B0C5greet4name5timesS2S_SitF","target":"s:9SwiftDemo0B0C"},{"kind":"memberOf","source":"s:9SwiftDemo0B0C7versionSSvpZ","target":"s:9SwiftDemo0B0C"},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s9EscapableP","targetFallback":"Swift.Escapable"},{"kind":"conformsTo","source":"s:9SwiftDemo5PointV","target":"s:s8CopyableP","targetFallback":"Swift.Copyable"},{"kind":"memberOf","source":"s:9SwiftDemo5PointV11descriptionSSvp","target":"s:9SwiftDemo5PointV","sourceOrigin":{"identifier":"s:s23CustomStringConvertibleP11descriptionSSvp","displayName":"CustomStringConvertible.description"}},{"kind":"memberOf","source":"s:9SwiftDemo5PointV6lengthSdvp","target":"s:9SwiftDemo5PointV"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s9EscapableP","targetFallback":"Swift.Escapable"},{"kind":"conformsTo","source":"s:9SwiftDemo6FlavorO","target":"s:s8CopyableP","targetFallback":"Swift.Copyable"},{"kind":"memberOf","source":"s:9SwiftDemo6FlavorO11descriptionSSvp","target":"s:9SwiftDemo6FlavorO","sourceOrigin":{"identifier":"s:s23CustomStringConvertibleP11descriptionSSvp","displayName":"CustomStringConvertible.description"}},{"kind":"conformsTo","source":"s:9SwiftDemo5ShapeP","target":"s:9SwiftDemo7GreeterP"},{"kind":"requirementOf","source":"s:9SwiftDemo5ShapeP4areaSdvp","target":"s:9SwiftDemo5ShapeP"},{"kind":"requirementOf","source":"s:9SwiftDemo5ShapeP5sidesSivpZ","target":"s:9SwiftDemo5ShapeP"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4nameSSvp","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC11vertexCountSivp","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC6sharedACvpZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4nameACSgSS_tcfc","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale2byySd_tF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale2byySi_tF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC4makeACyFZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonC8describeySSACSgFZ","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo7PolygonCyAA5PointVSicip","target":"s:9SwiftDemo7PolygonC"},{"kind":"conformsTo","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo5ShapeP"},{"kind":"conformsTo","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo7GreeterP"},{"kind":"inheritsFrom","source":"s:9SwiftDemo6SquareC","target":"s:9SwiftDemo7PolygonC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4sideSdvp","target":"s:9SwiftDemo6SquareC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4sideACSd_tcfc","target":"s:9SwiftDemo6SquareC"},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC4areaSdvp","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo5ShapeP4areaSdvp","displayName":"Shape.area"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5sidesSivpZ","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo5ShapeP5sidesSivpZ","displayName":"Shape.sides"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5greet4nameS2S_tF","target":"s:9SwiftDemo6SquareC","sourceOrigin":{"identifier":"s:9SwiftDemo7GreeterP5greet4nameS2S_tF","displayName":"Greeter.greet(name:)"}},{"kind":"memberOf","source":"s:9SwiftDemo6SquareC5scale2byySd_tF","target":"s:9SwiftDemo6SquareC"},{"kind":"overrides","source":"s:9SwiftDemo6SquareC5scale2byySd_tF","target":"s:9SwiftDemo7PolygonC5scale2byySd_tF"},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO","target":"s:9SwiftDemo13PrecipitationO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp","displayName":"RawRepresentable.hashValue"}},{"kind":"memberOf","source":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo13PrecipitationO","target":"s:9SwiftDemo13PrecipitationO","sourceOrigin":{"identifier":"s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF","displayName":"RawRepresentable.hash(into:)"}},{"kind":"memberOf","source":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo13PrecipitationO","target":"s:9SwiftDemo13PrecipitationO","sourceOrigin":{"identifier":"s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ","displayName":"Equatable.!=(_:_:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo13PrecipitationO","target":"s:SQ","targetFallback":"Swift.Equatable"},{"kind":"conformsTo","source":"s:9SwiftDemo13PrecipitationO","target":"s:SH","targetFallback":"Swift.Hashable"},{"kind":"conformsTo","source":"s:9SwiftDemo13PrecipitationO","target":"s:SY","targetFallback":"Swift.RawRepresentable"},{"kind":"memberOf","source":"s:9SwiftDemo13PrecipitationO4rainyA2CmF","target":"s:9SwiftDemo13PrecipitationO"},{"kind":"memberOf","source":"s:9SwiftDemo13PrecipitationO4snowyA2CmF","target":"s:9SwiftDemo13PrecipitationO"},{"kind":"memberOf","source":"s:9SwiftDemo13PrecipitationO4noneyA2CmF","target":"s:9SwiftDemo13PrecipitationO"},{"kind":"memberOf","source":"s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc","target":"s:9SwiftDemo13PrecipitationO","sourceOrigin":{"identifier":"s:SY8rawValuexSg03RawB0Qz_tcfc","displayName":"RawRepresentable.init(rawValue:)"}},{"kind":"memberOf","source":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp::SYNTHESIZED::s:9SwiftDemo10ShapeErrorO","target":"s:9SwiftDemo10ShapeErrorO","sourceOrigin":{"identifier":"s:s5ErrorP10FoundationE20localizedDescriptionSSvp","displayName":"Error.localizedDescription"}},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s5ErrorP","targetFallback":"Swift.Error"},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"conformsTo","source":"s:9SwiftDemo10ShapeErrorO","target":"s:s16SendableMetatypeP","targetFallback":"Swift.SendableMetatype"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo10ShapeErrorO7unknownyA2CmF","target":"s:9SwiftDemo10ShapeErrorO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO6lengthyACSdcACmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4noneyA2CmF","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp","target":"s:9SwiftDemo11MeasurementO4UnitV"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc","target":"s:9SwiftDemo11MeasurementO4UnitV"},{"kind":"memberOf","source":"s:9SwiftDemo11MeasurementO6isNoneSbvp","target":"s:9SwiftDemo11MeasurementO"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5innerAA5PointVvp","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5outerAA5PointVvp","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV6expand2byySd_tF","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:9SwiftDemo4RingV1poiyA2C_ACtFZ","target":"s:9SwiftDemo4RingV"},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pqd_0_YKXEqd_0_YKs5ErrorRd_0_Ri_d__r0_lF","displayName":"Actor.withSerialExecutor(_:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE18withSerialExecutoryqd__qd__Scf_pYaqd_0_YKYCXEYaqd_0_YKs5ErrorRd_0_Ri_d__r0_lF","displayName":"Actor.withSerialExecutor(_:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE20preconditionIsolated_4file4lineySSyXK_s12StaticStringVSutF","displayName":"Actor.preconditionIsolated(_:file:line:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE14assertIsolated_4file4lineySSyXK_s12StaticStringVSutF","displayName":"Actor.assertIsolated(_:file:line:)"}},{"kind":"memberOf","source":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF::SYNTHESIZED::s:9SwiftDemo7CounterC","target":"s:9SwiftDemo7CounterC","sourceOrigin":{"identifier":"s:ScA12_ConcurrencyE14assumeIsolated_4file4lineqd__qd__xYiKXE_s12StaticStringVSutKs8SendableRd__lF","displayName":"Actor.assumeIsolated(_:file:line:)"}},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:ScA","targetFallback":"_Concurrency.Actor"},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"conformsTo","source":"s:9SwiftDemo7CounterC","target":"s:s16SendableMetatypeP","targetFallback":"Swift.SendableMetatype"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC5valueSivp","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterCACycfc","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC9incrementSiyF","target":"s:9SwiftDemo7CounterC"},{"kind":"memberOf","source":"s:9SwiftDemo7CounterC5labelSSyF","target":"s:9SwiftDemo7CounterC"},{"kind":"conformsTo","source":"s:9SwiftDemo6CanvasC","target":"s:s8SendableP","targetFallback":"Swift.Sendable"},{"kind":"memberOf","source":"s:9SwiftDemo6CanvasCACycfc","target":"s:9SwiftDemo6CanvasC"},{"kind":"memberOf","source":"s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF","target":"s:9SwiftDemo6CanvasC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderCACycfc","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC4eachyyySiXEF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC6updateyyAA5PointVzF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC10modernOnlyyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC11legacyFetchyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo6LoaderC8oldFetchyyF","target":"s:9SwiftDemo6LoaderC"},{"kind":"memberOf","source":"s:9SwiftDemo7TrackerC9liveCountSivpZ","target":"s:9SwiftDemo7TrackerC"},{"kind":"memberOf","source":"s:9SwiftDemo7TrackerC2idSivp","target":"s:9SwiftDemo7TrackerC"},{"kind":"memberOf","source":"s:9SwiftDemo7TrackerC2idACSi_tcfc","target":"s:9SwiftDemo7TrackerC"},{"kind":"memberOf","source":"s:9SwiftDemo7TrackerC4sameACyF","target":"s:9SwiftDemo7TrackerC"}]} \ No newline at end of file diff --git a/metadata-generator/src/CMakeLists.txt b/metadata-generator/src/CMakeLists.txt index ef99b399c..11f96abb4 100644 --- a/metadata-generator/src/CMakeLists.txt +++ b/metadata-generator/src/CMakeLists.txt @@ -43,9 +43,11 @@ set(GENERATOR_HEADERS Swift/ProbeEmitter.h Swift/ProbeVerifier.h Swift/SwiftSource.h + Swift/SwiftSurface.h Swift/SwiftTypes.h Swift/SwiftIR.h Swift/SymbolGraphLoader.h + Swift/ThunkEmitter.h TypeScript/SwiftDefinitionWriter.h ) @@ -83,9 +85,11 @@ set(GENERATOR_SOURCES Swift/ProbeEmitter.cpp Swift/ProbeVerifier.cpp Swift/SwiftSource.cpp + Swift/SwiftSurface.cpp Swift/SwiftTypes.cpp Swift/SwiftIR.cpp Swift/SymbolGraphLoader.cpp + Swift/ThunkEmitter.cpp TypeScript/SwiftDefinitionWriter.cpp ) diff --git a/metadata-generator/src/Swift/SwiftSurface.cpp b/metadata-generator/src/Swift/SwiftSurface.cpp new file mode 100644 index 000000000..98eed23d0 --- /dev/null +++ b/metadata-generator/src/Swift/SwiftSurface.cpp @@ -0,0 +1,163 @@ +#include "SwiftSurface.h" + +namespace Swift { + +namespace { + +const IntegerWidth kIntegerWidths[] = { + {"i64", "Int", true}, {"i8", "Int8", true}, + {"i16", "Int16", true}, {"i32", "Int32", true}, + {"i64", "Int64", true}, {"u64", "UInt", false}, + {"u8", "UInt8", false}, {"u16", "UInt16", false}, + {"u32", "UInt32", false}, {"u64", "UInt64", false}, +}; + +const char* const kIntegerUSRs[] = { + KnownTypes::kInt, KnownTypes::kInt8, KnownTypes::kInt16, + KnownTypes::kInt32, KnownTypes::kInt64, KnownTypes::kUInt, + KnownTypes::kUInt8, KnownTypes::kUInt16, KnownTypes::kUInt32, + KnownTypes::kUInt64, +}; + +SwiftSurface::MemberKind memberKind(SymbolKind kind) { + switch (kind) { + case SymbolKind::Initializer: + return SwiftSurface::kInitializer; + case SymbolKind::InstanceMethod: + return SwiftSurface::kInstanceMethod; + case SymbolKind::TypeMethod: + return SwiftSurface::kStaticMethod; + case SymbolKind::InstanceProperty: + return SwiftSurface::kInstanceProperty; + case SymbolKind::TypeProperty: + return SwiftSurface::kStaticProperty; + case SymbolKind::Variable: + return SwiftSurface::kVariable; + case SymbolKind::EnumCase: + return SwiftSurface::kEnumCase; + default: + return SwiftSurface::kFunction; + } +} + +} // namespace + +int SwiftSurface::indexOf(const std::string& symbolId) const { + auto it = typeIndex.find(symbolId); + return it == typeIndex.end() ? -1 : it->second; +} + +const TypeNode& unwrappedNode(const BridgedType& type) { + const TypeNode& node = type.node; + if (type.optional && !node.children.empty() && + (node.kind == TypeNode::Kind::Optional || + node.kind == TypeNode::Kind::ImplicitlyUnwrappedOptional)) { + return node.children[0]; + } + return node; +} + +const IntegerWidth* integerWidth(const BridgedType& type) { + const std::string& usr = unwrappedNode(type).usr(); + for (size_t i = 0; i < sizeof(kIntegerUSRs) / sizeof(kIntegerUSRs[0]); i++) { + if (usr == kIntegerUSRs[i]) { + return &kIntegerWidths[i]; + } + } + return nullptr; +} + +std::string signatureCode(const SwiftSurface& surface, + const BridgedType& type) { + std::string code; + switch (type.bridge) { + case Bridge::Void: + code = "v"; + break; + case Bridge::Bool: + code = "b"; + break; + case Bridge::Integer: + code = integerWidth(type) ? integerWidth(type)->code : "i64"; + break; + case Bridge::Floating: + code = unwrappedNode(type).usr() == KnownTypes::kFloat ? "f32" : "f64"; + break; + case Bridge::String: + code = "s"; + break; + case Bridge::ClassHandle: + case Bridge::StructBox: + code = "o" + std::to_string(surface.indexOf(type.symbolId)); + break; + case Bridge::EnumCase: + code = "e" + std::to_string(surface.indexOf(type.symbolId)); + break; + case Bridge::None: + code = "?"; + break; + } + return type.optional ? code + "?" : code; +} + +SwiftSurface describeSurface(const Module& module, + const Classification& classification) { + SwiftSurface surface; + for (const auto& entry : module.symbols) { + const Symbol& symbol = entry.second; + const Capability* capability = classification.find(entry.first); + if (!capability || capability->tier != Tier::SwiftGenerated || + !isNominalType(symbol.kind) || symbol.kind == SymbolKind::Protocol) { + continue; + } + SwiftSurface::TypeKind kind = + symbol.kind == SymbolKind::Struct ? SwiftSurface::kStruct + : symbol.kind == SymbolKind::Enum ? SwiftSurface::kEnum + : symbol.kind == SymbolKind::Actor ? SwiftSurface::kActor + : SwiftSurface::kClass; + int index = static_cast(surface.types.size()); + surface.types.push_back(SwiftSurface::Type{&symbol, index, kind, -1}); + surface.typeIndex[symbol.preciseId] = index; + } + for (auto& type : surface.types) { + type.superIndex = surface.indexOf(type.symbol->superclassId); + } + + for (const auto& entry : module.symbols) { + const Symbol& symbol = entry.second; + const Capability* capability = classification.find(entry.first); + if (!capability || capability->tier != Tier::SwiftGenerated || + !isCallableKind(symbol.kind)) { + continue; + } + const Symbol* owner = + symbol.parentId.empty() ? nullptr : module.find(symbol.parentId); + + SwiftSurface::Member member; + member.symbol = &symbol; + member.capability = capability; + member.owner = owner ? surface.indexOf(owner->preciseId) : -1; + member.kind = memberKind(symbol.kind); + member.flags = + (symbol.isThrowing ? SwiftSurface::kThrows : 0) | + (symbol.isSettable && member.kind != SwiftSurface::kEnumCase + ? SwiftSurface::kSettable + : 0) | + (capability->ambiguousOverload ? SwiftSurface::kAmbiguous : 0); + member.result = capability->result; + if (member.kind == SwiftSurface::kEnumCase) { + member.result.bridge = Bridge::EnumCase; + member.result.symbolId = owner ? owner->preciseId : ""; + member.result.optional = false; + } + for (size_t i = 0; i < capability->parameters.size(); i++) { + member.signature += (i > 0 ? "," : "") + + signatureCode(surface, capability->parameters[i]); + } + member.signature += ">" + signatureCode(surface, member.result); + surface.members.push_back(std::move(member)); + } + return surface; +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/SwiftSurface.h b/metadata-generator/src/Swift/SwiftSurface.h new file mode 100644 index 000000000..6f84807cd --- /dev/null +++ b/metadata-generator/src/Swift/SwiftSurface.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include + +#include "CapabilityClassifier.h" +#include "SwiftIR.h" + +namespace Swift { + +// What a module registers with the runtime: the shared model behind the +// thunks (ThunkEmitter) and the TypeScript declarations +// (SwiftDefinitionWriter), so the two cannot disagree. Kinds, flags and +// signature codes are those of NativeScript/runtime/SwiftInterop.h. +struct SwiftSurface { + enum TypeKind { kClass = 0, kActor = 1, kStruct = 2, kEnum = 3 }; + enum MemberKind { + kInitializer = 0, + kInstanceMethod = 1, + kStaticMethod = 2, + kInstanceProperty = 3, + kStaticProperty = 4, + kFunction = 5, + kVariable = 6, + kEnumCase = 7, + }; + enum Flags { kThrows = 1 << 0, kSettable = 1 << 1, kAmbiguous = 1 << 2 }; + + struct Type { + const Symbol* symbol; + int index; + TypeKind kind; + // Type index of the registered superclass, or -1. + int superIndex; + }; + + struct Member { + const Symbol* symbol; + const Capability* capability; + // Type index, or -1 for module-level functions and variables. + int owner; + MemberKind kind; + int flags; + std::string signature; + // The value the member produces: the owner for initializers and enum + // cases, the property type for properties. + BridgedType result; + }; + + std::vector types; + std::vector members; + + // Type index of `symbolId`, or -1 when the type is not registered. + int indexOf(const std::string& symbolId) const; + + std::map typeIndex; +}; + +SwiftSurface describeSurface(const Module& module, + const Classification& classification); + +// Signature code of one value ("i64", "o3?", ...). +std::string signatureCode(const SwiftSurface& surface, const BridgedType& type); + +// Signed/unsigned integer width of an Integer bridge: {code, Swift type, +// signed}. +struct IntegerWidth { + const char* code; + const char* swiftType; + bool isSigned; +}; +const IntegerWidth* integerWidth(const BridgedType& type); + +// The type a BridgedType names without its optional wrapper. +const TypeNode& unwrappedNode(const BridgedType& type); + +} // namespace Swift diff --git a/metadata-generator/src/Swift/ThunkEmitter.cpp b/metadata-generator/src/Swift/ThunkEmitter.cpp new file mode 100644 index 000000000..fe6d8f0b8 --- /dev/null +++ b/metadata-generator/src/Swift/ThunkEmitter.cpp @@ -0,0 +1,609 @@ +#include "ThunkEmitter.h" + +#include + +#include +#include +#include + +#include "SwiftSource.h" +#include "SwiftSurface.h" + +namespace Swift { + +namespace { + +// Byte offsets of the API table slots used at registration. +constexpr int kRegisterModuleSlot = 10 * 8; +constexpr int kRegisterTypeSlot = 11 * 8; +constexpr int kRegisterMemberSlot = 12 * 8; + +std::string quoted(const std::string& text) { + std::string out = "\""; + for (char c : text) { + if (c == '"' || c == '\\') { + out += '\\'; + } + out += c; + } + return out + "\""; +} + +class Emitter { + public: + Emitter(const Module& module, const Classification& classification) + : _module(module), + _classification(classification), + _surface(describeSurface(module, classification)) {} + + ThunkSource run() { + ThunkSource result; + result.registerSymbol = "ns_swift_register_" + _module.name; + + std::string thunks; + for (const auto& member : _surface.members) { + thunks += emitMember(member); + } + + result.fingerprint = fingerprint(_registrations); + result.thunkCount = _thunkCount; + result.source = header() + support() + enumHelpers() + typeIndexFunction() + + thunks + registration(result); + return result; + } + + private: + int typeIndexOf(const std::string& id) const { return _surface.indexOf(id); } + + std::string typeName(const std::string& id) const { + const Symbol* symbol = _module.find(id); + return symbol ? qualifiedTypeName(_module, *symbol) : ""; + } + + // Swift expression reading slot `slot` as the non-optional value of + // `type`, for conversions that cannot fail. + std::string primitiveRead(const BridgedType& type, int slot) const { + std::string index = std::to_string(slot); + switch (type.bridge) { + case Bridge::Bool: + return "rt.bool(" + index + ")"; + case Bridge::Integer: { + const IntegerWidth* info = integerWidth(type); + std::string swiftType = info ? info->swiftType : "Int"; + bool isSigned = !info || info->isSigned; + std::string raw = + isSigned ? "rt.int64(" + index + ")" : "rt.uint64(" + index + ")"; + if (swiftType == "Int64" || swiftType == "UInt64") { + return raw; + } + // The runtime has range-checked the value against the width. + return swiftType + "(truncatingIfNeeded: " + raw + ")"; + } + case Bridge::Floating: { + const std::string& usr = unwrappedNode(type).usr(); + if (usr == KnownTypes::kFloat) { + return "Float(rt.double(" + index + "))"; + } + if (usr == KnownTypes::kCGFloat) { + return "CGFloat(rt.double(" + index + "))"; + } + return "rt.double(" + index + ")"; + } + case Bridge::String: + return "rt.string(" + index + ")"; + default: + return ""; + } + } + + // Lines binding `name` to argument `slot`; `label` describes it in errors. + std::string readArgument(const BridgedType& type, int slot, + const std::string& name, + const std::string& label) const { + std::string index = std::to_string(slot); + std::string cast; + std::string expected; + switch (type.bridge) { + case Bridge::ClassHandle: + cast = "rt.object(" + index + ") as? " + typeName(type.symbolId); + expected = typeName(type.symbolId); + break; + case Bridge::StructBox: + cast = "(rt.object(" + index + ") as? __NSBox<" + + typeName(type.symbolId) + ">)?.value"; + expected = typeName(type.symbolId); + break; + case Bridge::EnumCase: + cast = "__nsEnum" + std::to_string(typeIndexOf(type.symbolId)) + + "(rt.string(" + index + "))"; + expected = "a case of " + typeName(type.symbolId); + break; + default: { + std::string read = primitiveRead(type, slot); + if (type.optional) { + return " let " + name + " = rt.isNull(" + index + + ") ? nil : " + read + "\n"; + } + return " let " + name + " = " + read + "\n"; + } + } + std::string failure = "return rt.throwTypeError(" + + quoted(label + " must be " + expected) + ")"; + if (!type.optional) { + return " guard let " + name + " = " + cast + " else { " + failure + + " }\n"; + } + return " var " + name + ": " + valueTypeName(type) + "? = nil\n" + + " if !rt.isNull(" + index + ") {\n" + + " guard let value = " + cast + " else { " + failure + " }\n" + + " " + name + " = value\n" + " }\n"; + } + + std::string valueTypeName(const BridgedType& type) const { + if (!type.symbolId.empty()) { + return typeName(type.symbolId); + } + return swiftTypeText(unwrappedNode(type), _module); + } + + // Statements returning `value` (a non-optional expression of `type`). + std::string returnValue(const BridgedType& type, + const std::string& value) const { + switch (type.bridge) { + case Bridge::Void: + return "rt.returnVoid()"; + case Bridge::Bool: + return "rt.returnBool(" + value + ")"; + case Bridge::Integer: { + const IntegerWidth* info = integerWidth(type); + if (info && !info->isSigned) { + return "rt.returnUInt64(UInt64(" + value + "))"; + } + return "rt.returnInt64(Int64(" + value + "))"; + } + case Bridge::Floating: + return "rt.returnDouble(Double(" + value + "))"; + case Bridge::String: + return "rt.returnString(" + value + ")"; + case Bridge::ClassHandle: + return "rt.returnObject(" + value + ", __nsTypeIndex(" + value + ", " + + std::to_string(typeIndexOf(type.symbolId)) + "))"; + case Bridge::StructBox: + return "rt.returnObject(__NSBox(" + value + "), " + + std::to_string(typeIndexOf(type.symbolId)) + ")"; + case Bridge::EnumCase: + return "rt.returnString(__nsEnumName" + + std::to_string(typeIndexOf(type.symbolId)) + "(" + value + "))"; + case Bridge::None: + return "rt.returnVoid()"; + } + return "rt.returnVoid()"; + } + + std::string returnResult(const BridgedType& type, + const std::string& indent) const { + if (type.optional) { + return indent + "if let result {\n" + indent + " " + + returnValue(type, "result") + "\n" + indent + "} else {\n" + + indent + " rt.returnNull()\n" + indent + "}\n"; + } + return indent + returnValue(type, "result") + "\n"; + } + + // Receiver binding for instance members; returns the receiver expression. + std::string bindReceiver(const Symbol& owner, std::string& body) const { + std::string type = qualifiedTypeName(_module, owner); + std::string failure = + "return rt.throwTypeError(" + quoted("receiver must be " + type) + ")"; + if (owner.kind == SymbolKind::Struct) { + body += " guard let box = rt.object(0) as? __NSBox<" + type + + "> else { " + failure + " }\n"; + // Mutating members and setters change the boxed copy in place. + return "box.value"; + } + if (owner.kind == SymbolKind::Enum) { + body += " guard let receiver = __nsEnum" + + std::to_string(typeIndexOf(owner.preciseId)) + + "(rt.string(0)) else { " + failure + " }\n"; + return "receiver"; + } + body += " guard let receiver = rt.object(0) as? " + type + " else { " + + failure + " }\n"; + return "receiver"; + } + + std::string thunkHeader(int index) const { + return "private func __nsThunk" + std::to_string(index) + + "(_ call: UnsafeMutableRawPointer, _ args: UnsafeRawPointer?, _ " + "count: Int) {\n" + " let rt = __NSCall(call: call, args: args)\n"; + } + + std::string availabilityGuard(const Invocation& invocation, + const Symbol& symbol) const { + if (invocation.availability.empty()) { + return ""; + } + std::string platformVersion = + llvm::StringRef(invocation.availability).rsplit(',').first.trim().str(); + return " guard #available(" + invocation.availability + + ") else { return rt.throwMessage(" + + quoted(symbol.name + " requires " + platformVersion) + ") }\n"; + } + + std::string emitMember(const SwiftSurface::Member& member) { + const Symbol& symbol = *member.symbol; + const Capability& capability = *member.capability; + Invocation invocation = describeInvocation(_module, symbol, capability); + const Symbol* owner = + symbol.parentId.empty() ? nullptr : _module.find(symbol.parentId); + int ownerIndex = member.owner; + int kind = member.kind; + int flags = member.flags; + const std::string& signature = member.signature; + const BridgedType& result = member.result; + + if (kind == SwiftSurface::kEnumCase) { + // Case values are their names; nothing to call. + addRegistration(ownerIndex, kind, flags, capability.jsName, symbol.name, + signature, "nil", "nil"); + return ""; + } + + std::string code; + bool hasReceiver = invocation.needsReceiver; + int firstArgument = hasReceiver ? 1 : 0; + + // Getter or call. + int getterIndex = _thunkCount++; + code += "// " + symbol.preciseId + "\n" + thunkHeader(getterIndex); + code += availabilityGuard(invocation, symbol); + std::string receiver; + if (hasReceiver) { + receiver = bindReceiver(*owner, code); + } + std::vector arguments; + for (size_t i = 0; i < capability.parameters.size(); i++) { + std::string name = "a" + std::to_string(i); + code += readArgument(capability.parameters[i], + firstArgument + static_cast(i), name, + "argument " + std::to_string(i + 1)); + arguments.push_back(name); + } + std::string expression = + invocationExpression(invocation, receiver, arguments); + std::string binding = result.bridge == Bridge::Void ? "_" : "result"; + std::string resultType = invocation.resultType; + if (symbol.isThrowing) { + code += " do {\n let " + binding + ": " + resultType + " = " + + expression + "\n" + returnResult(result, " ") + + " } catch {\n rt.throwError(error)\n }\n"; + } else { + code += " let " + binding + ": " + resultType + " = " + expression + + "\n" + returnResult(result, " "); + } + code += "}\n\n"; + + std::string setterName = "nil"; + if (flags & SwiftSurface::kSettable) { + int setterIndex = _thunkCount++; + code += + "// " + symbol.preciseId + " (setter)\n" + thunkHeader(setterIndex); + code += availabilityGuard(invocation, symbol); + std::string setterReceiver; + if (hasReceiver) { + setterReceiver = bindReceiver(*owner, code); + } + code += + readArgument(capability.result, firstArgument, "newValue", "value"); + code += " " + + assignmentStatement(invocation, setterReceiver, "newValue") + + "\n"; + code += " rt.returnVoid()\n}\n\n"; + setterName = "__nsThunk" + std::to_string(setterIndex); + } + + addRegistration(ownerIndex, kind, flags, capability.jsName, symbol.name, + signature, "__nsThunk" + std::to_string(getterIndex), + setterName); + return code; + } + + void addRegistration(int owner, int kind, int flags, + const std::string& jsName, const std::string& swiftName, + const std::string& signature, const std::string& thunk, + const std::string& setter) { + _registrations.push_back( + " registerMember(registrar, " + std::to_string(owner) + ", " + + std::to_string(kind) + ", " + std::to_string(flags) + ", " + + quoted(jsName) + ", " + quoted(swiftName) + ", " + quoted(signature) + + ", " + thunk + ", " + setter + ")"); + } + + std::string header() const { + std::string out = "// Generated by objc-metadata-generator from the " + + _module.name + + " symbol graphs. Do not edit.\n" + "// NativeScript Swift interop thunks, ABI " + + std::to_string(kThunkABIVersion) + + ": see NativeScript/runtime/SwiftInterop.h.\n" + "import Foundation\n" + "import " + + _module.name + "\n"; + std::set overlays; + for (const auto& entry : _module.symbols) { + const Capability* capability = _classification.find(entry.first); + if (capability && capability->tier == Tier::SwiftGenerated && + !entry.second.declaringModule.empty()) { + overlays.insert(entry.second.declaringModule); + } + } + for (const auto& overlay : overlays) { + out += "import " + overlay + "\n"; + } + return out + "\n"; + } + + static std::string support() { + return R"swift(private typealias __NSThunk = @convention(c) (UnsafeMutableRawPointer, UnsafeRawPointer?, Int) -> Void +private typealias __NSRelease = @convention(c) (UnsafeMutableRawPointer) -> Void + +private final class __NSBox { + var value: Value + init(_ value: Value) { self.value = value } +} + +// Reads arguments (24-byte slots) and reports results through the runtime's +// API table, whose address is the first word of the call context. +private struct __NSCall { + let call: UnsafeMutableRawPointer + let args: UnsafeRawPointer? + + private func slot(_ index: Int, _: Function.Type) -> Function { + call.load(as: UnsafeRawPointer.self).load(fromByteOffset: index * 8, as: Function.self) + } + + func isNull(_ i: Int) -> Bool { args!.load(fromByteOffset: i * 24, as: UInt32.self) == 0 } + func bool(_ i: Int) -> Bool { args!.load(fromByteOffset: i * 24 + 8, as: UInt8.self) != 0 } + func int64(_ i: Int) -> Int64 { args!.load(fromByteOffset: i * 24 + 8, as: Int64.self) } + func uint64(_ i: Int) -> UInt64 { args!.load(fromByteOffset: i * 24 + 8, as: UInt64.self) } + func double(_ i: Int) -> Double { args!.load(fromByteOffset: i * 24 + 8, as: Double.self) } + func string(_ i: Int) -> String { + let base = args!.load(fromByteOffset: i * 24 + 8, as: UnsafePointer?.self) + let length = Int(args!.load(fromByteOffset: i * 24 + 16, as: UInt64.self)) + return String(decoding: UnsafeBufferPointer(start: base, count: length), as: UTF8.self) + } + func object(_ i: Int) -> AnyObject { + let pointer = args!.load(fromByteOffset: i * 24 + 8, as: UnsafeMutableRawPointer.self) + return Unmanaged.fromOpaque(pointer).takeUnretainedValue() + } + + func returnVoid() { + slot(0, (@convention(c) (UnsafeMutableRawPointer) -> Void).self)(call) + } + func returnBool(_ value: Bool) { + slot(1, (@convention(c) (UnsafeMutableRawPointer, UInt8) -> Void).self)(call, value ? 1 : 0) + } + func returnInt64(_ value: Int64) { + slot(2, (@convention(c) (UnsafeMutableRawPointer, Int64) -> Void).self)(call, value) + } + func returnUInt64(_ value: UInt64) { + slot(3, (@convention(c) (UnsafeMutableRawPointer, UInt64) -> Void).self)(call, value) + } + func returnDouble(_ value: Double) { + slot(4, (@convention(c) (UnsafeMutableRawPointer, Double) -> Void).self)(call, value) + } + func returnString(_ value: String) { + var value = value + value.withUTF8 { + slot(5, (@convention(c) (UnsafeMutableRawPointer, UnsafePointer?, Int) -> Void).self)( + call, $0.baseAddress, $0.count) + } + } + func returnNull() { + slot(6, (@convention(c) (UnsafeMutableRawPointer) -> Void).self)(call) + } + func returnObject(_ object: AnyObject, _ typeIndex: UInt32) { + slot(7, (@convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer, UInt32) -> Void).self)( + call, Unmanaged.passRetained(object).toOpaque(), typeIndex) + } + func throwError(_ error: any Error) { + report(String(describing: error), String(reflecting: type(of: error))) + } + func throwMessage(_ message: String) { + report(message, "") + } + func throwTypeError(_ message: String) { + var message = message + message.withUTF8 { + slot(9, (@convention(c) (UnsafeMutableRawPointer, UnsafePointer?, Int) -> Void).self)( + call, $0.baseAddress, $0.count) + } + } + private func report(_ message: String, _ type: String) { + var message = message + var type = type + message.withUTF8 { messageBytes in + type.withUTF8 { typeBytes in + slot(8, (@convention(c) (UnsafeMutableRawPointer, UnsafePointer?, Int, + UnsafePointer?, Int) -> Void).self)( + call, messageBytes.baseAddress, messageBytes.count, typeBytes.baseAddress, typeBytes.count) + } + } + } +} + +private func __nsRelease(_ object: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(object).release() +} + +)swift"; + } + + std::string enumHelpers() const { + std::string out; + for (const auto& type : _surface.types) { + const Symbol& symbol = *type.symbol; + if (symbol.kind != SymbolKind::Enum) { + continue; + } + std::string typeName = qualifiedTypeName(_module, symbol); + std::string availability = availabilityCondition(_module, symbol); + std::string attribute = + availability.empty() ? "" : "@available(" + availability + ")\n"; + std::string index = std::to_string(type.index); + std::vector cases; + for (const auto& id : symbol.memberIds) { + const Symbol* member = _module.find(id); + if (member && member->kind == SymbolKind::EnumCase) { + cases.push_back(member->baseName); + } + } + out += attribute + "private func __nsEnum" + index + + "(_ name: String) -> " + typeName + "? {\n switch name {\n"; + for (const auto& name : cases) { + // Qualified: a case named `none` would otherwise mean Optional.none. + out += " case " + quoted(name) + ": return " + typeName + "." + + swiftIdentifier(name) + "\n"; + } + out += " default: return nil\n }\n}\n\n"; + out += attribute + "private func __nsEnumName" + index + + "(_ value: " + typeName + ") -> String {\n switch value {\n"; + for (const auto& name : cases) { + out += " case " + typeName + "." + swiftIdentifier(name) + + ": return " + quoted(name) + "\n"; + } + out += " @unknown default: return String(describing: value)\n }\n}\n\n"; + } + return out; + } + + // Dynamic type index of a returned object: most derived classes first. + std::string typeIndexFunction() const { + std::vector classes; + for (const auto& type : _surface.types) { + if (type.symbol->kind == SymbolKind::Class || + type.symbol->kind == SymbolKind::Actor) { + classes.push_back(&type); + } + } + auto depth = [&](const Symbol* symbol) { + int value = 0; + for (const Symbol* current = symbol; + current && !current->superclassId.empty(); + current = _module.find(current->superclassId)) { + value++; + } + return value; + }; + std::stable_sort( + classes.begin(), classes.end(), + [&](const SwiftSurface::Type* a, const SwiftSurface::Type* b) { + return depth(a->symbol) > depth(b->symbol); + }); + + std::string out = + "private func __nsTypeIndex(_ object: AnyObject, _ declared: UInt32) " + "-> UInt32 {\n"; + for (const SwiftSurface::Type* type : classes) { + if (depth(type->symbol) == 0) { + // No registered subclass can be more specific than a root class. + continue; + } + std::string check = "if object is " + + qualifiedTypeName(_module, *type->symbol) + + " { return " + std::to_string(type->index) + " }"; + std::string availability = availabilityCondition(_module, *type->symbol); + if (availability.empty()) { + out += " " + check + "\n"; + } else { + out += " if #available(" + availability + ") { " + check + " }\n"; + } + } + return out + " return declared\n}\n\n"; + } + + std::string registration(const ThunkSource& result) const { + std::string out = "#if hasAttribute(c)\n@c(" + result.registerSymbol + + ")\n#else\n@_cdecl(\"" + result.registerSymbol + + "\")\n#endif\n" + "public func __nsRegister_" + + _module.name + + "(_ registrar: UnsafeMutableRawPointer) {\n" + " let api = registrar.load(as: UnsafeRawPointer.self)\n" + " let registerModule = api.load(fromByteOffset: " + + std::to_string(kRegisterModuleSlot) + + ", as: (@convention(c) (UnsafeMutableRawPointer, UInt32, " + "UnsafePointer, " + "UnsafePointer, __NSRelease) -> Void).self)\n" + " let registerType = api.load(fromByteOffset: " + + std::to_string(kRegisterTypeSlot) + + ", as: (@convention(c) (UnsafeMutableRawPointer, UInt32, " + "UInt32, UnsafePointer, " + "UnsafePointer, Int32) -> Void).self)\n" + " let registerMember = api.load(fromByteOffset: " + + std::to_string(kRegisterMemberSlot) + + ", as: (@convention(c) (UnsafeMutableRawPointer, Int32, " + "UInt32, UInt32, " + "UnsafePointer, UnsafePointer, " + "UnsafePointer, __NSThunk?, " + "__NSThunk?) -> Void).self)\n\n" + " registerModule(registrar, " + + std::to_string(kThunkABIVersion) + ", " + + quoted(_module.name) + ", " + quoted(result.fingerprint) + + ", __nsRelease)\n"; + for (const auto& type : _surface.types) { + const Symbol& symbol = *type.symbol; + int kind = type.kind; + out += " registerType(registrar, " + std::to_string(type.index) + ", " + + std::to_string(kind) + ", " + quoted(symbol.name) + ", " + + quoted(qualifiedTypeName(_module, symbol)) + ", " + + std::to_string(type.superIndex) + ")\n"; + } + for (const auto& line : _registrations) { + out += line + "\n"; + } + return out + "}\n"; + } + + std::string fingerprint(const std::vector& registrations) const { + // FNV-1a over everything registered, so the value changes with the + // surface but not with emitter formatting. + uint64_t hash = 1469598103934665603ull; + auto mix = [&](const std::string& text) { + for (unsigned char c : text) { + hash ^= c; + hash *= 1099511628211ull; + } + hash ^= '\n'; + hash *= 1099511628211ull; + }; + mix(_module.name); + for (const auto& type : _surface.types) { + mix(qualifiedTypeName(_module, *type.symbol) + "#" + + std::to_string(type.index)); + } + for (const auto& line : registrations) { + mix(line); + } + char buffer[17]; + std::snprintf(buffer, sizeof(buffer), "%016llx", + static_cast(hash)); + return buffer; + } + + const Module& _module; + const Classification& _classification; + SwiftSurface _surface; + std::vector _registrations; + int _thunkCount = 0; +}; + +} // namespace + +ThunkSource emitThunks(const Module& module, + const Classification& classification) { + return Emitter(module, classification).run(); +} + +} // namespace Swift diff --git a/metadata-generator/src/Swift/ThunkEmitter.h b/metadata-generator/src/Swift/ThunkEmitter.h new file mode 100644 index 000000000..0657601e6 --- /dev/null +++ b/metadata-generator/src/Swift/ThunkEmitter.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "CapabilityClassifier.h" +#include "SwiftIR.h" + +namespace Swift { + +// ABI version the emitted thunks implement; must match NS_SWIFT_ABI_VERSION +// in NativeScript/runtime/SwiftInterop.h, which documents the contract. +constexpr int kThunkABIVersion = 1; + +struct ThunkSource { + std::string source; + // Exported C symbol the runtime calls to register the module. + std::string registerSymbol; + // Changes whenever the registered surface changes. + std::string fingerprint; + int thunkCount = 0; +}; + +// Swift source registering every SwiftGenerated type and member of `module` +// with the NativeScript runtime, one thunk per callable. Compile it in a +// module that can import `module`. +ThunkSource emitThunks(const Module& module, + const Classification& classification); + +} // namespace Swift diff --git a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp index 1c7c11453..bb2667f8d 100644 --- a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp +++ b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.cpp @@ -1,27 +1,595 @@ #include "SwiftDefinitionWriter.h" +#include + +#include +#include #include +#include "Swift/SwiftSource.h" +#include "Swift/SwiftSurface.h" + namespace TypeScript { -std::string SwiftDefinitionWriter::write() { - std::ostringstream out; - out << "// Generated from Swift symbol graphs for module " << _module.name - << ".\n"; - out << "// Type-only: no Swift members are callable from JavaScript yet.\n\n"; +using namespace Swift; + +namespace { + +using Member = SwiftSurface::Member; + +// One JS name on one owner, as NativeScript/runtime/SwiftInterop.mm groups +// members. +struct Group { + int owner; + SwiftSurface::MemberKind kind; + std::string jsName; + std::vector overloads; +}; + +bool isReserved(const std::string& name) { + static const std::set reserved = { + "break", "case", "catch", "class", "const", "continue", + "debugger", "default", "delete", "do", "else", "enum", + "export", "extends", "false", "finally", "for", "function", + "if", "import", "in", "instanceof", "new", "null", + "return", "super", "switch", "this", "throw", "true", + "try", "typeof", "var", "void", "while", "with", + "yield", "let", "static", "implements", "interface", "package", + "private", "protected", "public", "await", "arguments", "eval"}; + return reserved.count(name) > 0; +} + +bool isIdentifier(const std::string& name) { + if (name.empty() || + !(llvm::isAlpha(name[0]) || name[0] == '_' || name[0] == '$')) { + return false; + } + for (char c : name) { + if (!(llvm::isAlnum(c) || c == '_' || c == '$')) { + return false; + } + } + return true; +} + +std::string propertyKey(const std::string& name) { + return isIdentifier(name) ? name : "\"" + name + "\""; +} + +std::string parameterName(const Parameter& parameter, size_t index) { + std::string name = !parameter.internalName.empty() ? parameter.internalName + : parameter.label; + if (!isIdentifier(name)) { + return "arg" + std::to_string(index); + } + return isReserved(name) ? name + "_" : name; +} + +// Swift display name of a signature code, as the runtime spells it in typed +// keys ("scale(by: Int)"). +std::string codeDisplayName(const SwiftSurface& surface, + const BridgedType& type) { + std::string name; + switch (type.bridge) { + case Bridge::Void: + name = "Void"; + break; + case Bridge::Bool: + name = "Bool"; + break; + case Bridge::Integer: { + std::string code = signatureCode(surface, type); + bool isSigned = code[0] == 'i'; + std::string bits = + llvm::StringRef(code).drop_front().take_while(llvm::isDigit).str(); + name = + std::string(isSigned ? "Int" : "UInt") + (bits == "64" ? "" : bits); + break; + } + case Bridge::Floating: + name = + unwrappedNode(type).usr() == KnownTypes::kFloat ? "Float" : "Double"; + break; + case Bridge::String: + name = "String"; + break; + case Bridge::ClassHandle: + case Bridge::StructBox: + case Bridge::EnumCase: { + int index = surface.indexOf(type.symbolId); + name = index >= 0 ? surface.types[index].symbol->name : "?"; + break; + } + case Bridge::None: + name = "?"; + break; + } + return type.optional ? name + "?" : name; +} + +std::string typedKey(const SwiftSurface& surface, const Member& member) { + const Symbol& symbol = *member.symbol; + std::string key = symbol.baseName + "("; + for (size_t i = 0; i < member.capability->parameters.size(); i++) { + if (i > 0) { + key += ", "; + } + std::string label = + i < symbol.parameters.size() ? symbol.parameters[i].label : ""; + key += (label.empty() ? "_" : label) + ": " + + codeDisplayName(surface, member.capability->parameters[i]); + } + return key + ")"; +} + +class Writer { + public: + Writer(const Module& module, const Classification& classification) + : _module(module), _surface(describeSurface(module, classification)) {} + + std::string write() { + buildGroups(); - for (const auto& id : _module.topLevelIds) { - const Swift::Symbol* symbol = _module.find(id); - if (!symbol || !Swift::isNominalType(symbol->kind)) { - continue; + _out << "// Generated by objc-metadata-generator from the " << _module.name + << " symbol graphs. Do not edit.\n" + << "// The JavaScript surface ns:swift exposes for " << _module.name + << ": every declaration is backed by a generated thunk.\n\n" + << "declare module \"ns:swift/" << _module.name << "\" {\n"; + + for (const auto& type : _surface.types) { + if (type.kind == SwiftSurface::kEnum) { + writeEnum(type); + } else { + writeClass(type); + } } - if (symbol->kind == Swift::SymbolKind::Protocol) { - out << "interface " << symbol->name << " {}\n"; - } else { - out << "declare class " << symbol->name << " {}\n"; + writeModuleMembers(); + + _out << "}\n\n" + << "declare module \"ns:swift\" {\n" + << " interface SwiftModules {\n" + << " " << propertyKey(_module.name) << ": typeof import(\"ns:swift/" + << _module.name << "\");\n" + << " }\n" + << "}\n"; + return _out.str(); + } + + private: + void buildGroups() { + std::map, size_t> index; + for (const auto& member : _surface.members) { + auto key = std::make_tuple(member.owner, static_cast(member.kind), + member.capability->jsName); + auto it = index.find(key); + if (it == index.end()) { + index.emplace(key, _groups.size()); + _groups.push_back( + Group{member.owner, member.kind, member.capability->jsName, {}}); + it = index.find(key); + } + _groups[it->second].overloads.push_back(&member); + } + + // Inherited overloads the subclass does not override (see BuildGroups in + // SwiftInterop.mm). + for (auto& group : _groups) { + if (group.kind != SwiftSurface::kInstanceMethod || group.owner < 0) { + continue; + } + for (int ancestor = _surface.types[group.owner].superIndex; ancestor >= 0; + ancestor = _surface.types[ancestor].superIndex) { + auto inherited = index.find(std::make_tuple( + ancestor, static_cast(group.kind), group.jsName)); + if (inherited == index.end()) { + continue; + } + for (const Member* candidate : _groups[inherited->second].overloads) { + bool overridden = false; + for (const Member* own : group.overloads) { + overridden |= own->symbol->name == candidate->symbol->name && + own->signature == candidate->signature; + } + if (!overridden) { + group.overloads.push_back(candidate); + } + } + } + } + } + + bool isA(int type, int expected) const { + for (int current = type; current >= 0; + current = _surface.types[current].superIndex) { + if (current == expected) { + return true; + } } + return false; } - return out.str(); + + // Whether some JS value is accepted as both `a` and `b` (overload + // resolution in the runtime would then see both). + bool overlaps(const BridgedType& a, const BridgedType& b) const { + if (a.optional && b.optional) { + return true; + } + auto numeric = [](Bridge bridge) { + return bridge == Bridge::Integer || bridge == Bridge::Floating; + }; + auto textual = [](Bridge bridge) { + return bridge == Bridge::String || bridge == Bridge::EnumCase; + }; + if (numeric(a.bridge) && numeric(b.bridge)) { + return true; + } + if (textual(a.bridge) && textual(b.bridge)) { + return true; + } + if (a.bridge == Bridge::Bool && b.bridge == Bridge::Bool) { + return true; + } + bool objects = + (a.bridge == Bridge::ClassHandle || a.bridge == Bridge::StructBox) && + (b.bridge == Bridge::ClassHandle || b.bridge == Bridge::StructBox); + if (objects) { + int left = _surface.indexOf(a.symbolId); + int right = _surface.indexOf(b.symbolId); + return isA(left, right) || isA(right, left); + } + return false; + } + + bool ambiguousWithin(const Group& group, const Member& member) const { + const auto& parameters = member.capability->parameters; + for (const Member* other : group.overloads) { + if (other == &member || + other->capability->parameters.size() != parameters.size()) { + continue; + } + bool all = true; + for (size_t i = 0; all && i < parameters.size(); i++) { + all = overlaps(parameters[i], other->capability->parameters[i]); + } + if (all) { + return true; + } + } + return false; + } + + // Keys installed per overload when the group has several (see + // OverloadKeys in SwiftInterop.mm). + std::vector> overloadKeys( + const Group& group) const { + std::vector> keys; + if (group.overloads.size() < 2) { + return keys; + } + std::map counts; + for (const Member* member : group.overloads) { + counts[member->symbol->name]++; + } + for (const Member* member : group.overloads) { + keys.emplace_back(counts[member->symbol->name] == 1 + ? member->symbol->name + : typedKey(_surface, *member), + member); + } + return keys; + } + + std::string typeName(const BridgedType& type) const { + int index = _surface.indexOf(type.symbolId); + return index >= 0 ? _surface.types[index].symbol->name : "unknown"; + } + + std::string inputType(const BridgedType& type) const { + std::string ts; + switch (type.bridge) { + case Bridge::Bool: + ts = "boolean"; + break; + case Bridge::Integer: + ts = "number | bigint"; + break; + case Bridge::Floating: + ts = "number"; + break; + case Bridge::String: + ts = "string"; + break; + case Bridge::ClassHandle: + case Bridge::StructBox: + case Bridge::EnumCase: + ts = typeName(type); + break; + default: + ts = "never"; + break; + } + return type.optional ? ts + " | null | undefined" : ts; + } + + std::string outputType(const BridgedType& type) const { + std::string ts; + switch (type.bridge) { + case Bridge::Void: + return "void"; + case Bridge::Bool: + ts = "boolean"; + break; + case Bridge::Integer: + case Bridge::Floating: + ts = "number"; + break; + case Bridge::String: + ts = "string"; + break; + case Bridge::ClassHandle: + case Bridge::StructBox: + case Bridge::EnumCase: + ts = typeName(type); + break; + case Bridge::None: + ts = "never"; + break; + } + return type.optional ? ts + " | null" : ts; + } + + std::string parameterList(const Member& member, + const std::string& receiver = "") const { + std::vector parts; + if (!receiver.empty()) { + parts.push_back("value: " + receiver); + } + const auto& parameters = member.capability->parameters; + for (size_t i = 0; i < parameters.size(); i++) { + const Parameter* parameter = i < member.symbol->parameters.size() + ? &member.symbol->parameters[i] + : nullptr; + std::string name = + parameter ? parameterName(*parameter, i) : "arg" + std::to_string(i); + parts.push_back(name + ": " + inputType(parameters[i])); + } + return llvm::join(parts, ", "); + } + + // `{ x: number; y: number }` for initializers JS can call with labels. + std::string labeledParameters(const Member& member) const { + const auto& parameters = member.capability->parameters; + if (parameters.empty()) { + return ""; + } + std::vector fields; + for (size_t i = 0; i < parameters.size(); i++) { + const std::string& label = i < member.symbol->parameters.size() + ? member.symbol->parameters[i].label + : ""; + if (label.empty()) { + return ""; + } + fields.push_back(propertyKey(label) + ": " + inputType(parameters[i])); + } + return "{ " + llvm::join(fields, "; ") + " }"; + } + + void writeDoc(const Symbol& symbol, const std::string& indent) { + std::vector lines; + if (!symbol.docComment.empty()) { + llvm::SmallVector docLines; + llvm::StringRef(symbol.docComment).split(docLines, '\n'); + for (llvm::StringRef line : docLines) { + lines.push_back(line.str()); + } + } + for (const Availability* availability : + applicableAvailability(_module, symbol)) { + if (availability->isUnconditionallyDeprecated || + availability->deprecated) { + std::string message = availability->message; + if (message.empty() && !availability->renamed.empty()) { + message = "Renamed to `" + availability->renamed + "`."; + } + lines.push_back("@deprecated" + (message.empty() ? "" : " " + message)); + } + } + std::string condition = availabilityCondition(_module, symbol); + if (!condition.empty()) { + lines.push_back( + "@remarks Requires " + + llvm::StringRef(condition).rsplit(',').first.trim().str() + + "; throws on earlier versions."); + } + if (lines.empty()) { + return; + } + _out << indent << "/**\n"; + for (const auto& line : lines) { + std::string safe = line; + for (size_t at = safe.find("*/"); at != std::string::npos; + at = safe.find("*/")) { + safe.replace(at, 2, "* /"); + } + _out << indent << " *" << (safe.empty() ? "" : " " + safe) << "\n"; + } + _out << indent << " */\n"; + } + + void writeMethodGroup(const Group& group, const std::string& indent, + const std::string& prefix, + const std::string& receiver = "") { + for (const Member* member : group.overloads) { + if (ambiguousWithin(group, *member)) { + continue; + } + writeDoc(*member->symbol, indent); + _out << indent << prefix << propertyKey(group.jsName) << "(" + << parameterList(*member, receiver) + << "): " << outputType(member->result) << ";\n"; + } + for (const auto& key : overloadKeys(group)) { + writeDoc(*key.second->symbol, indent); + _out << indent << prefix << propertyKey(key.first) << "(" + << parameterList(*key.second, receiver) + << "): " << outputType(key.second->result) << ";\n"; + } + } + + void writeClass(const SwiftSurface::Type& type) { + const Symbol& symbol = *type.symbol; + writeDoc(symbol, " "); + _out << " export class " << symbol.name; + if (type.superIndex >= 0) { + _out << " extends " << _surface.types[type.superIndex].symbol->name; + } + _out << " {\n"; + + bool hasInitializer = false; + for (const Group& group : _groups) { + if (group.owner != type.index || + group.kind != SwiftSurface::kInitializer) { + continue; + } + hasInitializer = true; + for (const Member* member : group.overloads) { + writeDoc(*member->symbol, " "); + _out << " constructor(" << parameterList(*member) << ");\n"; + std::string labeled = labeledParameters(*member); + if (!labeled.empty()) { + _out << " constructor(args: " << labeled << ");\n"; + } + } + } + if (!hasInitializer) { + _out << " private constructor();\n"; + } + + for (const Group& group : _groups) { + if (group.owner != type.index) { + continue; + } + const Member& first = *group.overloads[0]; + switch (group.kind) { + case SwiftSurface::kInstanceProperty: + case SwiftSurface::kStaticProperty: + writeDoc(*first.symbol, " "); + _out << " " + << (group.kind == SwiftSurface::kStaticProperty ? "static " : "") + << ((first.flags & SwiftSurface::kSettable) ? "" : "readonly ") + << propertyKey(group.jsName) << ": " << outputType(first.result) + << ";\n"; + break; + case SwiftSurface::kInstanceMethod: + writeMethodGroup(group, " ", ""); + break; + case SwiftSurface::kStaticMethod: + writeMethodGroup(group, " ", "static "); + break; + default: + break; + } + } + _out << " }\n\n"; + } + + void writeEnum(const SwiftSurface::Type& type) { + const Symbol& symbol = *type.symbol; + std::vector cases; + for (const Group& group : _groups) { + if (group.owner == type.index && group.kind == SwiftSurface::kEnumCase) { + cases.push_back("\"" + group.jsName + "\""); + } + } + writeDoc(symbol, " "); + _out << " export type " << symbol.name << " = " + << (cases.empty() ? std::string("never") : llvm::join(cases, " | ")) + << ";\n"; + _out << " export const " << symbol.name << ": {\n"; + for (const Group& group : _groups) { + if (group.owner != type.index) { + continue; + } + const Member& first = *group.overloads[0]; + switch (group.kind) { + case SwiftSurface::kEnumCase: + _out << " readonly " << propertyKey(group.jsName) << ": \"" + << group.jsName << "\";\n"; + break; + case SwiftSurface::kInitializer: + // Enum initializers are exposed as `init`; they produce a case name. + for (const Member* member : group.overloads) { + writeDoc(*member->symbol, " "); + _out << " init(" << parameterList(*member) + << "): " << outputType(member->result) << ";\n"; + } + break; + case SwiftSurface::kStaticProperty: + writeDoc(*first.symbol, " "); + _out << " " + << ((first.flags & SwiftSurface::kSettable) ? "" : "readonly ") + << propertyKey(group.jsName) << ": " << outputType(first.result) + << ";\n"; + break; + case SwiftSurface::kInstanceProperty: + // A case name has no properties; instance members take it first. + writeDoc(*first.symbol, " "); + _out << " " << propertyKey(group.jsName) + << "(value: " << symbol.name << "): " << outputType(first.result) + << ";\n"; + break; + case SwiftSurface::kInstanceMethod: + writeMethodGroup(group, " ", "", symbol.name); + break; + case SwiftSurface::kStaticMethod: + writeMethodGroup(group, " ", ""); + break; + default: + break; + } + } + _out << " };\n\n"; + } + + void writeModuleMembers() { + for (const Group& group : _groups) { + if (group.owner >= 0) { + continue; + } + const Member& first = *group.overloads[0]; + if (!isIdentifier(group.jsName) || isReserved(group.jsName)) { + continue; + } + if (group.kind == SwiftSurface::kVariable) { + writeDoc(*first.symbol, " "); + _out << " export " + << ((first.flags & SwiftSurface::kSettable) ? "let " : "const ") + << group.jsName << ": " << outputType(first.result) << ";\n"; + continue; + } + for (const Member* member : group.overloads) { + if (ambiguousWithin(group, *member)) { + continue; + } + writeDoc(*member->symbol, " "); + _out << " export function " << group.jsName << "(" + << parameterList(*member) << "): " << outputType(member->result) + << ";\n"; + } + } + } + + const Module& _module; + SwiftSurface _surface; + std::vector _groups; + std::ostringstream _out; +}; + +} // namespace + +std::string SwiftDefinitionWriter::write() { + return Writer(_module, _classification).write(); } } // namespace TypeScript diff --git a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h index 97eb59403..be825314d 100644 --- a/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h +++ b/metadata-generator/src/TypeScript/SwiftDefinitionWriter.h @@ -2,22 +2,26 @@ #include +#include "Swift/CapabilityClassifier.h" #include "Swift/SwiftIR.h" namespace TypeScript { -// Writes `swift!.d.ts`. Declarations are type-only: they name the -// module's Swift types, but no Swift member is callable from JavaScript, so -// none is declared. +// Writes `swift!.d.ts`: the module's JavaScript surface as `ns:swift` +// exposes it. Only declarations with generated thunks are declared, through +// the same registration model the thunks are emitted from (SwiftSurface), so +// the declarations describe exactly what runs. class SwiftDefinitionWriter { public: - explicit SwiftDefinitionWriter(const Swift::Module& module) - : _module(module) {} + SwiftDefinitionWriter(const Swift::Module& module, + const Swift::Classification& classification) + : _module(module), _classification(classification) {} std::string write(); private: const Swift::Module& _module; + const Swift::Classification& _classification; }; } // namespace TypeScript diff --git a/metadata-generator/src/main.cpp b/metadata-generator/src/main.cpp index f8cdf6bd2..eea794f49 100644 --- a/metadata-generator/src/main.cpp +++ b/metadata-generator/src/main.cpp @@ -24,6 +24,7 @@ #include "Swift/ProbeEmitter.h" #include "Swift/ProbeVerifier.h" #include "Swift/SymbolGraphLoader.h" +#include "Swift/ThunkEmitter.h" #include "TypeScript/DefinitionWriter.h" #include "TypeScript/DocSetManager.h" #include "TypeScript/SwiftDefinitionWriter.h" @@ -87,6 +88,11 @@ llvm::cl::opt cla_swiftWorkDir( llvm::cl::desc("Scratch directory for --swift-verify (default: a " "temporary directory)"), llvm::cl::value_desc("")); +llvm::cl::opt cla_swiftThunkOutputDir( + "swift-thunk-output", + llvm::cl::desc("Directory to write Swift interop thunks " + "(+NativeScript.swift)"), + llvm::cl::value_desc("")); llvm::cl::opt cla_swiftCoverageOutputDir( "swift-coverage-output", llvm::cl::desc("Directory to write Swift coverage reports " @@ -352,19 +358,15 @@ int main(int argc, const char** argv) for (const auto& entry : swiftModules.modules) { const Swift::Module& module = entry.second; - if (!cla_outputDtsFolder.empty()) { - TypeScript::SwiftDefinitionWriter swiftWriter(module); - swiftFailed |= !writeFile(cla_outputDtsFolder, - "swift!" + module.name + ".d.ts", - swiftWriter.write()); - } if (!cla_swiftIROutputDir.empty()) { swiftFailed |= !writeFile(cla_swiftIROutputDir, module.name + ".swift-ir.json", Swift::dumpModuleJSON(module)); } - if (cla_swiftCoverageOutputDir.empty() && - cla_swiftProbeOutputDir.empty()) { + if (cla_outputDtsFolder.empty() && + cla_swiftCoverageOutputDir.empty() && + cla_swiftProbeOutputDir.empty() && + cla_swiftThunkOutputDir.empty()) { continue; } Swift::Classification classification; @@ -410,11 +412,25 @@ int main(int argc, const char** argv) } else { classification = Swift::classify(module); } + if (!cla_outputDtsFolder.empty()) { + TypeScript::SwiftDefinitionWriter swiftWriter(module, + classification); + swiftFailed |= !writeFile(cla_outputDtsFolder, + "swift!" + module.name + ".d.ts", + swiftWriter.write()); + } if (!cla_swiftCoverageOutputDir.empty()) { swiftFailed |= !writeFile( cla_swiftCoverageOutputDir, module.name + ".coverage.json", Swift::coverageJSON(module, classification, compilerRuns)); } + if (!cla_swiftThunkOutputDir.empty()) { + Swift::ThunkSource thunks = + Swift::emitThunks(module, classification); + swiftFailed |= !writeFile(cla_swiftThunkOutputDir, + module.name + "+NativeScript.swift", + thunks.source); + } if (!cla_swiftProbeOutputDir.empty()) { Swift::ProbeSource probes = Swift::emitProbes(module, classification); diff --git a/metadata-generator/tests/CMakeLists.txt b/metadata-generator/tests/CMakeLists.txt index 7d6353b3f..c2adca4d9 100644 --- a/metadata-generator/tests/CMakeLists.txt +++ b/metadata-generator/tests/CMakeLists.txt @@ -6,8 +6,10 @@ set(SWIFT_GENERATOR_SOURCES ${CMAKE_SOURCE_DIR}/src/Swift/ProbeVerifier.cpp ${CMAKE_SOURCE_DIR}/src/Swift/SwiftIR.cpp ${CMAKE_SOURCE_DIR}/src/Swift/SwiftSource.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/SwiftSurface.cpp ${CMAKE_SOURCE_DIR}/src/Swift/SwiftTypes.cpp ${CMAKE_SOURCE_DIR}/src/Swift/SymbolGraphLoader.cpp + ${CMAKE_SOURCE_DIR}/src/Swift/ThunkEmitter.cpp ${CMAKE_SOURCE_DIR}/src/TypeScript/SwiftDefinitionWriter.cpp ) @@ -16,6 +18,7 @@ add_executable(swift-symbolgraph-tests swift/SymbolGraphLoaderTests.cpp swift/SwiftTypesTests.cpp swift/ClassifierTests.cpp + swift/ThunkEmitterTests.cpp ${SWIFT_GENERATOR_SOURCES} ) target_include_directories(swift-symbolgraph-tests PRIVATE ${CMAKE_SOURCE_DIR}/src) @@ -23,6 +26,8 @@ target_compile_definitions(swift-symbolgraph-tests PRIVATE SWIFT_FIXTURE_DIR="${CMAKE_SOURCE_DIR}/TestFixtures/SwiftDemo" SWIFT_FIXTURE_GRAPHS_DIR="${CMAKE_SOURCE_DIR}/TestFixtures/SwiftDemo/symbolgraphs" SWIFT_SNAPSHOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}/swift/snapshots" + SWIFT_TEST_DIR="${CMAKE_CURRENT_SOURCE_DIR}/swift" + SWIFT_TYPES_DIR="${CMAKE_SOURCE_DIR}/../types" ) target_link_libraries(swift-symbolgraph-tests ${LLVM_LINKER_FLAGS}) set_target_properties(swift-symbolgraph-tests PROPERTIES diff --git a/metadata-generator/tests/swift/ClassifierTests.cpp b/metadata-generator/tests/swift/ClassifierTests.cpp index d043ddd7a..4e915eadc 100644 --- a/metadata-generator/tests/swift/ClassifierTests.cpp +++ b/metadata-generator/tests/swift/ClassifierTests.cpp @@ -6,6 +6,7 @@ #include "Swift/ProbeEmitter.h" #include "Swift/ProbeVerifier.h" #include "Swift/SwiftSource.h" +#include "SwiftToolchain.h" #include "TestHarness.h" #include "TestSupport.h" @@ -165,61 +166,6 @@ TEST(ProbeSnapshot) { emitProbes(demo(), classification()).source); } -namespace { - -// Directory holding SwiftDemo.swiftmodule built from the fixture sources, or -// "" when no Swift toolchain is available. -const std::string& fixtureModuleDirectory() { - static std::string directory = [] { - if (!llvm::sys::findProgramByName("xcrun")) { - return std::string(); - } - llvm::SmallString<128> path; - if (llvm::sys::fs::createUniqueDirectory("swift-fixture", path)) { - return std::string(); - } - std::string command = - "xcrun swiftc -emit-module -module-name SwiftDemo " - "-target arm64-apple-ios15.0-simulator " - "-sdk \"$(xcrun --sdk iphonesimulator --show-sdk-path)\" " - "-emit-module-path '" + - path.str().str() + - "/SwiftDemo.swiftmodule' '" SWIFT_FIXTURE_DIR - "'/Sources/SwiftDemo/*.swift"; - auto shell = llvm::sys::findProgramByName("sh"); - if (!shell || - llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}) != 0) { - return std::string(); - } - return path.str().str(); - }(); - return directory; -} - -VerifyOptions fixtureVerifyOptions() { - VerifyOptions options; - options.compiler = {"xcrun", "swiftc"}; - llvm::SmallString<128> sdkLog; - llvm::sys::fs::createTemporaryFile("sdk", "txt", sdkLog); - auto shell = llvm::sys::findProgramByName("sh"); - std::optional redirects[] = { - std::nullopt, llvm::StringRef(sdkLog), std::nullopt}; - llvm::sys::ExecuteAndWait( - *shell, {*shell, "-c", "xcrun --sdk iphonesimulator --show-sdk-path"}, - std::nullopt, redirects); - auto sdk = llvm::MemoryBuffer::getFile(sdkLog); - options.sdk = sdk ? (*sdk)->getBuffer().trim().str() : ""; - llvm::sys::fs::remove(sdkLog); - options.target = "arm64-apple-ios15.0-simulator"; - options.searchPaths = {fixtureModuleDirectory()}; - llvm::SmallString<128> work; - llvm::sys::fs::createUniqueDirectory("swift-verify", work); - options.workDirectory = work.str().str(); - return options; -} - -} // namespace - TEST(VerifierParsesDiagnostics) { std::string log = "/tmp/p.swift:12:7: error: value of type 'X' has no member 'y'\n" @@ -286,50 +232,16 @@ TEST(VerifierDemotesWhatTheCompilerRejects) { Tier::SwiftGenerated); } -// Builds the fixture module and type-checks the probes against it. +// Type-checks the probes against the separately compiled fixture module. TEST(ProbesTypeCheck) { - auto shell = llvm::sys::findProgramByName("sh"); - auto xcrun = llvm::sys::findProgramByName("xcrun"); - if (!shell || !xcrun) { - std::cout << " (skipped: xcrun not found)" << std::endl; + if (fixtureModuleDirectory().empty()) { + std::cout << " (skipped: no Swift toolchain)" << std::endl; return; } - - llvm::SmallString<128> directory; - REQUIRE(!llvm::sys::fs::createUniqueDirectory("swift-probes", directory)); - llvm::SmallString<128> probePath(directory); - llvm::sys::path::append(probePath, "probe.swift"); - { - std::error_code error; - llvm::raw_fd_ostream out(probePath, error, llvm::sys::fs::OF_Text); - REQUIRE(!error); - out << emitProbes(demo(), classification()).source; - } - - std::string dir = directory.str().str(); - std::string command = - "set -e; SDK=$(xcrun --sdk iphonesimulator --show-sdk-path); " - "TARGET=arm64-apple-ios15.0-simulator; " - "xcrun swiftc -emit-module -module-name SwiftDemo -target $TARGET -sdk " - "\"$SDK\" " - "-emit-module-path '" + - dir + - "/SwiftDemo.swiftmodule' '" SWIFT_FIXTURE_DIR - "'/Sources/SwiftDemo/*.swift; " - "xcrun swiftc -typecheck -I '" + - dir + "' -target $TARGET -sdk \"$SDK\" '" + probePath.str().str() + "'"; - llvm::SmallString<128> log(directory); - llvm::sys::path::append(log, "swiftc.log"); - std::optional redirects[] = { - std::nullopt, llvm::StringRef(log), llvm::StringRef(log)}; - int status = llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}, - std::nullopt, redirects); - if (status != 0) { - auto output = llvm::MemoryBuffer::getFile(log); - TestHarness::fail( - __FILE__, __LINE__, - "probes failed to type-check:\n" + - (output ? (*output)->getBuffer().str() : std::string("(no log)"))); + std::string errors = + typeCheckAgainstFixture(emitProbes(demo(), classification()).source); + if (!errors.empty()) { + TestHarness::fail(__FILE__, __LINE__, + "probes failed to type-check:\n" + errors); } - llvm::sys::fs::remove_directories(directory); } diff --git a/metadata-generator/tests/swift/SwiftToolchain.h b/metadata-generator/tests/swift/SwiftToolchain.h new file mode 100644 index 000000000..22b75eace --- /dev/null +++ b/metadata-generator/tests/swift/SwiftToolchain.h @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include "Swift/ProbeVerifier.h" + +// Helpers for tests that run the Swift compiler against the fixture module. +namespace TestSupport { + +// Directory holding SwiftDemo.swiftmodule built from the fixture sources, or +// "" when no Swift toolchain is available. +inline const std::string& fixtureModuleDirectory() { + static std::string directory = [] { + if (!llvm::sys::findProgramByName("xcrun")) { + return std::string(); + } + llvm::SmallString<128> path; + if (llvm::sys::fs::createUniqueDirectory("swift-fixture", path)) { + return std::string(); + } + std::string command = + "xcrun swiftc -emit-module -module-name SwiftDemo " + "-target arm64-apple-ios15.0-simulator " + "-sdk \"$(xcrun --sdk iphonesimulator --show-sdk-path)\" " + "-emit-module-path '" + + path.str().str() + + "/SwiftDemo.swiftmodule' '" SWIFT_FIXTURE_DIR + "'/Sources/SwiftDemo/*.swift"; + auto shell = llvm::sys::findProgramByName("sh"); + if (!shell || + llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}) != 0) { + return std::string(); + } + return path.str().str(); + }(); + return directory; +} + +inline Swift::VerifyOptions fixtureVerifyOptions() { + Swift::VerifyOptions options; + options.compiler = {"xcrun", "swiftc"}; + llvm::SmallString<128> sdkLog; + llvm::sys::fs::createTemporaryFile("sdk", "txt", sdkLog); + auto shell = llvm::sys::findProgramByName("sh"); + std::optional redirects[] = { + std::nullopt, llvm::StringRef(sdkLog), std::nullopt}; + llvm::sys::ExecuteAndWait( + *shell, {*shell, "-c", "xcrun --sdk iphonesimulator --show-sdk-path"}, + std::nullopt, redirects); + auto sdk = llvm::MemoryBuffer::getFile(sdkLog); + options.sdk = sdk ? (*sdk)->getBuffer().trim().str() : ""; + llvm::sys::fs::remove(sdkLog); + options.target = "arm64-apple-ios15.0-simulator"; + options.searchPaths = {fixtureModuleDirectory()}; + llvm::SmallString<128> work; + llvm::sys::fs::createUniqueDirectory("swift-verify", work); + options.workDirectory = work.str().str(); + return options; +} + +// Type-checks `source` against the fixture module; returns the compiler's +// output on failure and "" on success. +inline std::string typeCheckAgainstFixture(const std::string& source, + const std::string& extraFlags = "") { + llvm::SmallString<128> directory; + if (llvm::sys::fs::createUniqueDirectory("swift-typecheck", directory)) { + return "cannot create a temporary directory"; + } + llvm::SmallString<128> sourcePath(directory); + llvm::sys::path::append(sourcePath, "source.swift"); + { + std::error_code error; + llvm::raw_fd_ostream out(sourcePath, error, llvm::sys::fs::OF_Text); + out << source; + } + llvm::SmallString<128> log(directory); + llvm::sys::path::append(log, "swiftc.log"); + std::string command = + "xcrun swiftc -typecheck " + extraFlags + + " -target arm64-apple-ios15.0-simulator " + "-sdk \"$(xcrun --sdk iphonesimulator --show-sdk-path)\" -I '" + + fixtureModuleDirectory() + "' '" + sourcePath.str().str() + "'"; + auto shell = llvm::sys::findProgramByName("sh"); + std::optional redirects[] = { + std::nullopt, llvm::StringRef(log), llvm::StringRef(log)}; + int status = llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}, + std::nullopt, redirects); + std::string output; + if (status != 0) { + auto buffer = llvm::MemoryBuffer::getFile(log); + output = buffer ? (*buffer)->getBuffer().str() + : "compiler failed without output"; + } + llvm::sys::fs::remove_directories(directory); + return output; +} + +} // namespace TestSupport diff --git a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp index 6a838ee87..4c02843f9 100644 --- a/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp +++ b/metadata-generator/tests/swift/SymbolGraphLoaderTests.cpp @@ -7,6 +7,7 @@ #include #include +#include "Swift/CapabilityClassifier.h" #include "Swift/SymbolGraphLoader.h" #include "TestHarness.h" #include "TestSupport.h" @@ -73,15 +74,15 @@ TEST(TopLevelDeclarationsInSourceOrder) { for (const auto& id : demo().topLevelIds) { names.push_back(demo().find(id)->name); } - std::vector expected = {"Greeter", "Demo", - "Point", "Flavor", - "Shape", "Polygon", - "Square", "ShapeError", - "Measurement", "Ring", - "Counter", "Canvas", - "Loader", "makeDefaultPoint()", - "defaultFlavor", "globalCounter", - "Coordinates"}; + std::vector expected = { + "Greeter", "Demo", "Point", + "Flavor", "Shape", "Polygon", + "Square", "Precipitation", "ShapeError", + "Measurement", "Ring", "Counter", + "Canvas", "Loader", "makeDefaultPoint()", + "defaultFlavor", "globalCounter", "Coordinates", + "checkedSide(_:)", "echoInt8(_:)", "echoUInt64(_:)", + "largestInt()", "shout(_:)", "Tracker"}; CHECK_EQ(llvm::join(names, ","), llvm::join(expected, ",")); } @@ -436,7 +437,8 @@ TEST(TypeAliases) { TEST(IRSnapshot) { checkSnapshot("SwiftDemo.ir.json", dumpModuleJSON(demo())); } TEST(TypeScriptSnapshot) { - TypeScript::SwiftDefinitionWriter writer(demo()); + Classification classification = classify(demo()); + TypeScript::SwiftDefinitionWriter writer(demo(), classification); checkSnapshot("swift!SwiftDemo.d.ts", writer.write()); } diff --git a/metadata-generator/tests/swift/TestSupport.h b/metadata-generator/tests/swift/TestSupport.h index ee37a22db..29da1b0c0 100644 --- a/metadata-generator/tests/swift/TestSupport.h +++ b/metadata-generator/tests/swift/TestSupport.h @@ -69,39 +69,41 @@ inline std::string diagnosticCodes(const std::vector& diagnostics) { return llvm::join(codes, ", "); } -// Compares `actual` against a checked-in snapshot. NS_UPDATE_SNAPSHOTS=1 -// rewrites the snapshot instead. -inline void checkSnapshot(const std::string& fileName, - const std::string& actual) { - llvm::SmallString<256> snapshotPath(SWIFT_SNAPSHOT_DIR); - llvm::sys::path::append(snapshotPath, fileName); - +// Compares `actual` against the checked-in file at `path`. +// NS_UPDATE_SNAPSHOTS=1 rewrites the file instead. +inline void checkFile(const std::string& path, const std::string& actual) { if (const char* update = std::getenv("NS_UPDATE_SNAPSHOTS"); update && *update == '1') { std::error_code error; - llvm::raw_fd_ostream out(snapshotPath, error, llvm::sys::fs::OF_Text); + llvm::raw_fd_ostream out(path, error, llvm::sys::fs::OF_Text); REQUIRE(!error); out << actual; return; } - auto expected = llvm::MemoryBuffer::getFile(snapshotPath, /*IsText*/ true); + auto expected = llvm::MemoryBuffer::getFile(path, /*IsText*/ true); if (!expected) { - TestHarness::fail(__FILE__, __LINE__, - "missing snapshot " + snapshotPath.str().str() + - " (run with NS_UPDATE_SNAPSHOTS=1)"); + TestHarness::fail( + __FILE__, __LINE__, + "missing snapshot " + path + " (run with NS_UPDATE_SNAPSHOTS=1)"); return; } if ((*expected)->getBuffer() != actual) { - llvm::SmallString<256> actualPath(snapshotPath); - actualPath += ".actual"; + std::string actualPath = path + ".actual"; std::error_code error; llvm::raw_fd_ostream out(actualPath, error, llvm::sys::fs::OF_Text); out << actual; TestHarness::fail(__FILE__, __LINE__, - "snapshot mismatch: diff " + snapshotPath.str().str() + - " " + actualPath.str().str()); + "snapshot mismatch: diff " + path + " " + actualPath); } } +// Compares `actual` against tests/swift/snapshots/. +inline void checkSnapshot(const std::string& fileName, + const std::string& actual) { + llvm::SmallString<256> path(SWIFT_SNAPSHOT_DIR); + llvm::sys::path::append(path, fileName); + checkFile(path.str().str(), actual); +} + } // namespace TestSupport diff --git a/metadata-generator/tests/swift/ThunkEmitterTests.cpp b/metadata-generator/tests/swift/ThunkEmitterTests.cpp new file mode 100644 index 000000000..210e393ae --- /dev/null +++ b/metadata-generator/tests/swift/ThunkEmitterTests.cpp @@ -0,0 +1,133 @@ +#include "Swift/CapabilityClassifier.h" +#include "Swift/ThunkEmitter.h" +#include "SwiftToolchain.h" +#include "TestHarness.h" +#include "TestSupport.h" +#include "TypeScript/SwiftDefinitionWriter.h" + +using namespace Swift; +using namespace TestSupport; + +namespace { + +const ThunkSource& thunks() { + static ThunkSource source = emitThunks(demo(), classify(demo())); + return source; +} + +bool registers(const std::string& line) { + return thunks().source.find(line) != std::string::npos; +} + +} // namespace + +// TestRunner compiles this checked-in copy (TestFixtures/SwiftDemo/Interop), +// so it must be exactly what the generator emits. +TEST(ThunkSourceMatchesFixtureInterop) { + checkFile(SWIFT_FIXTURE_DIR "/Interop/SwiftDemo+NativeScript.swift", + thunks().source); +} + +TEST(ThunksTypeCheck) { + if (fixtureModuleDirectory().empty()) { + std::cout << " (skipped: no Swift toolchain)" << std::endl; + return; + } + std::string errors = + typeCheckAgainstFixture(thunks().source, "-parse-as-library"); + if (!errors.empty()) { + TestHarness::fail(__FILE__, __LINE__, + "thunks failed to type-check:\n" + errors); + } +} + +TEST(ThunkRegistration) { + CHECK_EQ(thunks().registerSymbol, std::string("ns_swift_register_SwiftDemo")); + CHECK_EQ(thunks().fingerprint.size(), size_t(16)); + CHECK(thunks().thunkCount > 0); + CHECK(registers("registerModule(registrar, 1, \"SwiftDemo\", \"" + + thunks().fingerprint + "\", __nsRelease)")); + // Instance method with labels; signature (String, Int) -> String. + CHECK(registers("\"greet\", \"greet(name:times:)\", \"s,i64>s\"")); + // Failable initializer of a class returns an optional object. + CHECK(registers("\"constructor\", \"init(name:)\", \"s>o")); + // Ambiguous overloads carry the flag (4) and stay distinct by signature. + CHECK(registers(", 1, 4, \"scale\", \"scale(by:)\", \"f64>v\"")); + CHECK(registers(", 1, 4, \"scale\", \"scale(by:)\", \"i64>v\"")); + // Enum cases register without a thunk. + CHECK(registers("\"vanilla\", \"vanilla\", \">e")); + // A case named `none` maps to the enum's case, not Optional.none. + CHECK(registers("case \"none\": return SwiftDemo.Precipitation.`none`")); + // Settable stored property registers a setter. + CHECK(registers("\"x\", \"x\", \">f64\", __nsThunk")); +} + +TEST(ThunkFingerprintTracksSurface) { + Classification classification = classify(demo()); + ThunkSource original = emitThunks(demo(), classification); + // Demoting one member changes the registered surface. + std::map rejections = { + {symbolAt(demo(), "Demo.greet(name:)")->preciseId, "test"}}; + ThunkSource reduced = emitThunks(demo(), classify(demo(), rejections)); + CHECK(original.fingerprint != reduced.fingerprint); + CHECK_EQ(emitThunks(demo(), classification).fingerprint, + original.fingerprint); +} + +// The generated declarations, with the runtime's types/ns-swift.d.ts, accept +// the documented usage and reject what the runtime rejects. Needs a `tsc` +// on PATH or in NS_TSC; skipped otherwise. +TEST(TypeScriptUsageCompiles) { + std::string tsc; + if (const char* configured = std::getenv("NS_TSC"); + configured && *configured) { + tsc = configured; + } else if (auto found = llvm::sys::findProgramByName("tsc")) { + tsc = *found; + } else { + std::cout << " (skipped: no tsc; set NS_TSC)" << std::endl; + return; + } + + llvm::SmallString<128> directory; + REQUIRE(!llvm::sys::fs::createUniqueDirectory("swift-tsc", directory)); + auto write = [&](const std::string& name, const std::string& content) { + llvm::SmallString<128> path(directory); + llvm::sys::path::append(path, name); + std::error_code error; + llvm::raw_fd_ostream out(path, error, llvm::sys::fs::OF_Text); + out << content; + return path.str().str(); + }; + Classification classification = classify(demo()); + write("swift-SwiftDemo.d.ts", + TypeScript::SwiftDefinitionWriter(demo(), classification).write()); + auto usage = + llvm::MemoryBuffer::getFile(SWIFT_TEST_DIR "/typescript/usage.ts"); + REQUIRE(usage); + std::string usagePath = + write("usage.ts", "/// \n" + "/// \n" + + (*usage)->getBuffer().str()); + + llvm::SmallString<128> log(directory); + llvm::sys::path::append(log, "tsc.log"); + std::string command = "'" + tsc + + "' --noEmit --strict --target es2022 --module esnext " + "--moduleResolution bundler --lib es2022 '" + + usagePath + "'"; + auto shell = llvm::sys::findProgramByName("sh"); + std::optional redirects[] = { + std::nullopt, llvm::StringRef(log), llvm::StringRef(log)}; + int status = llvm::sys::ExecuteAndWait(*shell, {*shell, "-c", command}, + std::nullopt, redirects); + if (status != 0) { + auto output = llvm::MemoryBuffer::getFile(log); + TestHarness::fail( + __FILE__, __LINE__, + "tsc rejected the declarations:\n" + + (output ? (*output)->getBuffer().str() : std::string())); + } + llvm::sys::fs::remove_directories(directory); +} diff --git a/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json b/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json index 1b8aaa47d..114155fec 100644 --- a/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json +++ b/metadata-generator/tests/swift/snapshots/SwiftDemo.coverage.json @@ -2,24 +2,24 @@ "module": "SwiftDemo", "totals": { "declarations": { - "total": 95, + "total": 113, "objc-direct": 0, - "swift-generated": 52, + "swift-generated": 68, "swift-specialized": 5, "type-only": 6, - "unsupported": 32, + "unsupported": 34, "not-applicable": 0 }, "callable": { - "total": 80, + "total": 96, "objc-direct": 0, - "swift-generated": 43, + "swift-generated": 57, "swift-specialized": 5, "type-only": 3, - "unsupported": 29, + "unsupported": 31, "not-applicable": 0 }, - "effectiveCallable": 43, + "effectiveCallable": 57, "compilerVerified": false, "compiledThunks": null, "runtimeTested": null @@ -35,63 +35,63 @@ "not-applicable": 0 }, "class": { - "total": 5, + "total": 6, "objc-direct": 0, - "swift-generated": 5, + "swift-generated": 6, "swift-specialized": 0, "type-only": 0, "unsupported": 0, "not-applicable": 0 }, "enum": { - "total": 3, + "total": 4, "objc-direct": 0, - "swift-generated": 1, + "swift-generated": 2, "swift-specialized": 0, "type-only": 0, "unsupported": 2, "not-applicable": 0 }, "enumCase": { - "total": 8, + "total": 11, "objc-direct": 0, - "swift-generated": 2, + "swift-generated": 5, "swift-specialized": 0, "type-only": 0, "unsupported": 6, "not-applicable": 0 }, "function": { - "total": 1, + "total": 6, "objc-direct": 0, - "swift-generated": 1, + "swift-generated": 6, "swift-specialized": 0, "type-only": 0, "unsupported": 0, "not-applicable": 0 }, "initializer": { - "total": 11, + "total": 13, "objc-direct": 0, - "swift-generated": 9, + "swift-generated": 11, "swift-specialized": 0, "type-only": 0, "unsupported": 2, "not-applicable": 0 }, "instanceMethod": { - "total": 31, + "total": 33, "objc-direct": 0, - "swift-generated": 12, + "swift-generated": 13, "swift-specialized": 5, "type-only": 1, - "unsupported": 13, + "unsupported": 14, "not-applicable": 0 }, "instanceProperty": { - "total": 18, + "total": 20, "objc-direct": 0, - "swift-generated": 12, + "swift-generated": 14, "swift-specialized": 0, "type-only": 1, "unsupported": 5, @@ -107,12 +107,12 @@ "not-applicable": 0 }, "operator": { - "total": 2, + "total": 3, "objc-direct": 0, "swift-generated": 0, "swift-specialized": 0, "type-only": 0, - "unsupported": 2, + "unsupported": 3, "not-applicable": 0 }, "protocol": { @@ -152,9 +152,9 @@ "not-applicable": 0 }, "typeProperty": { - "total": 4, + "total": 5, "objc-direct": 0, - "swift-generated": 3, + "swift-generated": 4, "swift-specialized": 0, "type-only": 1, "unsupported": 0, @@ -178,10 +178,10 @@ "enum-associated-values": 2, "external-type-extension": 2, "generic": 5, - "inout-parameter": 2, + "inout-parameter": 3, "main-actor": 2, "nested-type": 1, - "operator": 2, + "operator": 3, "owner-not-bridged": 10, "subscript": 1, "unbridged-type": 3 @@ -234,7 +234,7 @@ "reasons": [ "enum-associated-values" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:50" + "location": "file://Sources/SwiftDemo/Shapes.swift:55" }, { "id": "s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF", @@ -244,7 +244,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:51" + "location": "file://Sources/SwiftDemo/Shapes.swift:56" }, { "id": "s:9SwiftDemo10ShapeErrorO12tooManySidesyACSi_SitcACmF", @@ -254,7 +254,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:52" + "location": "file://Sources/SwiftDemo/Shapes.swift:57" }, { "id": "s:9SwiftDemo10ShapeErrorO7unknownyA2CmF", @@ -264,7 +264,23 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:53" + "location": "file://Sources/SwiftDemo/Shapes.swift:58" + }, + { + "id": "s:9SwiftDemo10echoUInt64ys0D0VADF", + "path": "echoUInt64(_:)", + "kind": "function", + "tier": "swift-generated", + "jsName": "echoUInt64", + "location": "file://Sources/SwiftDemo/Values.swift:10" + }, + { + "id": "s:9SwiftDemo10largestIntSiyF", + "path": "largestInt()", + "kind": "function", + "tier": "swift-generated", + "jsName": "largestInt", + "location": "file://Sources/SwiftDemo/Values.swift:11" }, { "id": "s:9SwiftDemo11Coordinatesa", @@ -274,7 +290,7 @@ "reasons": [ "type-alias" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:137" + "location": "file://Sources/SwiftDemo/Shapes.swift:142" }, { "id": "s:9SwiftDemo11MeasurementO", @@ -284,7 +300,7 @@ "reasons": [ "enum-associated-values" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:56" + "location": "file://Sources/SwiftDemo/Shapes.swift:61" }, { "id": "s:9SwiftDemo11MeasurementO4UnitV", @@ -294,7 +310,7 @@ "reasons": [ "nested-type" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:61" + "location": "file://Sources/SwiftDemo/Shapes.swift:66" }, { "id": "s:9SwiftDemo11MeasurementO4UnitV6symbolAESS_tcfc", @@ -304,7 +320,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:63" + "location": "file://Sources/SwiftDemo/Shapes.swift:68" }, { "id": "s:9SwiftDemo11MeasurementO4UnitV6symbolSSvp", @@ -314,7 +330,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:62" + "location": "file://Sources/SwiftDemo/Shapes.swift:67" }, { "id": "s:9SwiftDemo11MeasurementO4areayACSd_SdtcACmF", @@ -324,7 +340,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:58" + "location": "file://Sources/SwiftDemo/Shapes.swift:63" }, { "id": "s:9SwiftDemo11MeasurementO4noneyA2CmF", @@ -334,7 +350,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:59" + "location": "file://Sources/SwiftDemo/Shapes.swift:64" }, { "id": "s:9SwiftDemo11MeasurementO6isNoneSbvp", @@ -344,7 +360,7 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:66" + "location": "file://Sources/SwiftDemo/Shapes.swift:71" }, { "id": "s:9SwiftDemo11MeasurementO6lengthyACSdcACmF", @@ -354,7 +370,53 @@ "reasons": [ "owner-not-bridged" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:57" + "location": "file://Sources/SwiftDemo/Shapes.swift:62" + }, + { + "id": "s:9SwiftDemo11checkedSideyS2dKF", + "path": "checkedSide(_:)", + "kind": "function", + "tier": "swift-generated", + "jsName": "checkedSide", + "location": "file://Sources/SwiftDemo/Values.swift:4" + }, + { + "id": "s:9SwiftDemo13PrecipitationO", + "path": "Precipitation", + "kind": "enum", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Shapes.swift:51" + }, + { + "id": "s:9SwiftDemo13PrecipitationO4noneyA2CmF", + "path": "Precipitation.none", + "kind": "enumCase", + "tier": "swift-generated", + "jsName": "none", + "location": "file://Sources/SwiftDemo/Shapes.swift:52" + }, + { + "id": "s:9SwiftDemo13PrecipitationO4rainyA2CmF", + "path": "Precipitation.rain", + "kind": "enumCase", + "tier": "swift-generated", + "jsName": "rain", + "location": "file://Sources/SwiftDemo/Shapes.swift:52" + }, + { + "id": "s:9SwiftDemo13PrecipitationO4snowyA2CmF", + "path": "Precipitation.snow", + "kind": "enumCase", + "tier": "swift-generated", + "jsName": "snow", + "location": "file://Sources/SwiftDemo/Shapes.swift:52" + }, + { + "id": "s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc", + "path": "Precipitation.init(rawValue:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor" }, { "id": "s:9SwiftDemo13defaultFlavorAA0D0Ovp", @@ -362,7 +424,7 @@ "kind": "variable", "tier": "swift-generated", "jsName": "defaultFlavor", - "location": "file://Sources/SwiftDemo/Shapes.swift:135" + "location": "file://Sources/SwiftDemo/Shapes.swift:140" }, { "id": "s:9SwiftDemo13globalCounterSivp", @@ -370,7 +432,7 @@ "kind": "variable", "tier": "swift-generated", "jsName": "globalCounter", - "location": "file://Sources/SwiftDemo/Shapes.swift:136" + "location": "file://Sources/SwiftDemo/Shapes.swift:141" }, { "id": "s:9SwiftDemo16makeDefaultPointAA0E0VyF", @@ -378,14 +440,14 @@ "kind": "function", "tier": "swift-generated", "jsName": "makeDefaultPoint", - "location": "file://Sources/SwiftDemo/Shapes.swift:134" + "location": "file://Sources/SwiftDemo/Shapes.swift:139" }, { "id": "s:9SwiftDemo4RingV", "path": "Ring", "kind": "struct", "tier": "swift-generated", - "location": "file://Sources/SwiftDemo/Shapes.swift:72" + "location": "file://Sources/SwiftDemo/Shapes.swift:77" }, { "id": "s:9SwiftDemo4RingV1poiyA2C_ACtFZ", @@ -395,7 +457,7 @@ "reasons": [ "operator" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:86" + "location": "file://Sources/SwiftDemo/Shapes.swift:91" }, { "id": "s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc", @@ -403,7 +465,7 @@ "kind": "initializer", "tier": "swift-generated", "jsName": "constructor", - "location": "file://Sources/SwiftDemo/Shapes.swift:76" + "location": "file://Sources/SwiftDemo/Shapes.swift:81" }, { "id": "s:9SwiftDemo4RingV5innerAA5PointVvp", @@ -411,7 +473,7 @@ "kind": "instanceProperty", "tier": "swift-generated", "jsName": "inner", - "location": "file://Sources/SwiftDemo/Shapes.swift:73" + "location": "file://Sources/SwiftDemo/Shapes.swift:78" }, { "id": "s:9SwiftDemo4RingV5outerAA5PointVvp", @@ -419,7 +481,7 @@ "kind": "instanceProperty", "tier": "swift-generated", "jsName": "outer", - "location": "file://Sources/SwiftDemo/Shapes.swift:74" + "location": "file://Sources/SwiftDemo/Shapes.swift:79" }, { "id": "s:9SwiftDemo4RingV6expand2byySd_tF", @@ -427,7 +489,7 @@ "kind": "instanceMethod", "tier": "swift-generated", "jsName": "expand", - "location": "file://Sources/SwiftDemo/Shapes.swift:81" + "location": "file://Sources/SwiftDemo/Shapes.swift:86" }, { "id": "s:9SwiftDemo5PointV", @@ -506,12 +568,20 @@ ], "location": "file://Sources/SwiftDemo/Shapes.swift:5" }, + { + "id": "s:9SwiftDemo5shoutySSSgACF", + "path": "shout(_:)", + "kind": "function", + "tier": "swift-generated", + "jsName": "shout", + "location": "file://Sources/SwiftDemo/Values.swift:12" + }, { "id": "s:9SwiftDemo6CanvasC", "path": "Canvas", "kind": "class", "tier": "swift-generated", - "location": "file://Sources/SwiftDemo/Shapes.swift:102" + "location": "file://Sources/SwiftDemo/Shapes.swift:107" }, { "id": "s:9SwiftDemo6CanvasC4drawyyAA5Shape_pF", @@ -521,7 +591,7 @@ "reasons": [ "main-actor" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:104" + "location": "file://Sources/SwiftDemo/Shapes.swift:109" }, { "id": "s:9SwiftDemo6CanvasCACycfc", @@ -531,7 +601,7 @@ "reasons": [ "main-actor" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:103" + "location": "file://Sources/SwiftDemo/Shapes.swift:108" }, { "id": "s:9SwiftDemo6FlavorO", @@ -576,7 +646,7 @@ "path": "Loader", "kind": "class", "tier": "swift-generated", - "location": "file://Sources/SwiftDemo/Shapes.swift:107" + "location": "file://Sources/SwiftDemo/Shapes.swift:112" }, { "id": "s:9SwiftDemo6LoaderC10modernOnlyyyF", @@ -584,7 +654,7 @@ "kind": "instanceMethod", "tier": "swift-generated", "jsName": "modernOnly", - "location": "file://Sources/SwiftDemo/Shapes.swift:125" + "location": "file://Sources/SwiftDemo/Shapes.swift:130" }, { "id": "s:9SwiftDemo6LoaderC11legacyFetchyyF", @@ -592,7 +662,7 @@ "kind": "instanceMethod", "tier": "swift-generated", "jsName": "legacyFetch", - "location": "file://Sources/SwiftDemo/Shapes.swift:128" + "location": "file://Sources/SwiftDemo/Shapes.swift:133" }, { "id": "s:9SwiftDemo6LoaderC14withCompletionyyys6ResultOySSAA10ShapeErrorOGcF", @@ -602,7 +672,7 @@ "reasons": [ "closure" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:117" + "location": "file://Sources/SwiftDemo/Shapes.swift:122" }, { "id": "s:9SwiftDemo6LoaderC4eachyyySiXEF", @@ -612,7 +682,7 @@ "reasons": [ "closure" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:118" + "location": "file://Sources/SwiftDemo/Shapes.swift:123" }, { "id": "s:9SwiftDemo6LoaderC4load4path10Foundation4DataVSS_tKF", @@ -622,7 +692,7 @@ "reasons": [ "unbridged-type:Foundation.Data" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:110" + "location": "file://Sources/SwiftDemo/Shapes.swift:115" }, { "id": "s:9SwiftDemo6LoaderC4wait7secondsySd_tYaF", @@ -632,7 +702,7 @@ "reasons": [ "async" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:112" + "location": "file://Sources/SwiftDemo/Shapes.swift:117" }, { "id": "s:9SwiftDemo6LoaderC5fetch3urlSS10Foundation3URLV_tYaKF", @@ -642,7 +712,7 @@ "reasons": [ "async" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:111" + "location": "file://Sources/SwiftDemo/Shapes.swift:116" }, { "id": "s:9SwiftDemo6LoaderC5first2ofxSgSayxG_tlF", @@ -652,7 +722,7 @@ "reasons": [ "generic" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:115" + "location": "file://Sources/SwiftDemo/Shapes.swift:120" }, { "id": "s:9SwiftDemo6LoaderC6lookup5table3keySiSgSDySSSiG_SStF", @@ -662,7 +732,7 @@ "reasons": [ "collection" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:120" + "location": "file://Sources/SwiftDemo/Shapes.swift:125" }, { "id": "s:9SwiftDemo6LoaderC6updateyyAA5PointVzF", @@ -672,7 +742,7 @@ "reasons": [ "inout-parameter" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:122" + "location": "file://Sources/SwiftDemo/Shapes.swift:127" }, { "id": "s:9SwiftDemo6LoaderC8oldFetchyyF", @@ -680,7 +750,7 @@ "kind": "instanceMethod", "tier": "swift-generated", "jsName": "oldFetch", - "location": "file://Sources/SwiftDemo/Shapes.swift:131" + "location": "file://Sources/SwiftDemo/Shapes.swift:136" }, { "id": "s:9SwiftDemo6LoaderC9transformyxxAA5ShapeRzlF", @@ -690,7 +760,7 @@ "reasons": [ "generic" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:114" + "location": "file://Sources/SwiftDemo/Shapes.swift:119" }, { "id": "s:9SwiftDemo6LoaderCACycfc", @@ -698,7 +768,7 @@ "kind": "initializer", "tier": "swift-generated", "jsName": "constructor", - "location": "file://Sources/SwiftDemo/Shapes.swift:108" + "location": "file://Sources/SwiftDemo/Shapes.swift:113" }, { "id": "s:9SwiftDemo6SquareC", @@ -760,7 +830,7 @@ "path": "Counter", "kind": "actor", "tier": "swift-generated", - "location": "file://Sources/SwiftDemo/Shapes.swift:91" + "location": "file://Sources/SwiftDemo/Shapes.swift:96" }, { "id": "s:9SwiftDemo7CounterC5labelSSyF", @@ -768,7 +838,7 @@ "kind": "instanceMethod", "tier": "swift-generated", "jsName": "label", - "location": "file://Sources/SwiftDemo/Shapes.swift:98" + "location": "file://Sources/SwiftDemo/Shapes.swift:103" }, { "id": "s:9SwiftDemo7CounterC5valueSivp", @@ -778,7 +848,7 @@ "reasons": [ "actor-isolated" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:92" + "location": "file://Sources/SwiftDemo/Shapes.swift:97" }, { "id": "s:9SwiftDemo7CounterC9incrementSiyF", @@ -788,7 +858,7 @@ "reasons": [ "actor-isolated" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:94" + "location": "file://Sources/SwiftDemo/Shapes.swift:99" }, { "id": "s:9SwiftDemo7CounterCACycfc", @@ -796,7 +866,7 @@ "kind": "initializer", "tier": "swift-generated", "jsName": "constructor", - "location": "file://Sources/SwiftDemo/Shapes.swift:93" + "location": "file://Sources/SwiftDemo/Shapes.swift:98" }, { "id": "s:9SwiftDemo7GreeterP", @@ -917,6 +987,62 @@ ], "location": "file://Sources/SwiftDemo/Shapes.swift:30" }, + { + "id": "s:9SwiftDemo7TrackerC", + "path": "Tracker", + "kind": "class", + "tier": "swift-generated", + "location": "file://Sources/SwiftDemo/Values.swift:14" + }, + { + "id": "s:9SwiftDemo7TrackerC2idACSi_tcfc", + "path": "Tracker.init(id:)", + "kind": "initializer", + "tier": "swift-generated", + "jsName": "constructor", + "location": "file://Sources/SwiftDemo/Values.swift:18" + }, + { + "id": "s:9SwiftDemo7TrackerC2idSivp", + "path": "Tracker.id", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "id", + "location": "file://Sources/SwiftDemo/Values.swift:16" + }, + { + "id": "s:9SwiftDemo7TrackerC4sameACyF", + "path": "Tracker.same()", + "kind": "instanceMethod", + "tier": "swift-generated", + "jsName": "same", + "location": "file://Sources/SwiftDemo/Values.swift:25" + }, + { + "id": "s:9SwiftDemo7TrackerC9liveCountSivpZ", + "path": "Tracker.liveCount", + "kind": "typeProperty", + "tier": "swift-generated", + "jsName": "liveCount", + "location": "file://Sources/SwiftDemo/Values.swift:15" + }, + { + "id": "s:9SwiftDemo8echoInt8ys0D0VADF", + "path": "echoInt8(_:)", + "kind": "function", + "tier": "swift-generated", + "jsName": "echoInt8", + "location": "file://Sources/SwiftDemo/Values.swift:9" + }, + { + "id": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "path": "Precipitation.!=(_:_:)", + "kind": "operator", + "tier": "unsupported", + "reasons": [ + "operator" + ] + }, { "id": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO", "path": "Flavor.!=(_:_:)", @@ -936,6 +1062,13 @@ ], "location": "file://Sources/SwiftDemo/Extensions.swift:19" }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "path": "Precipitation.hashValue", + "kind": "instanceProperty", + "tier": "swift-generated", + "jsName": "hashValue" + }, { "id": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO", "path": "Flavor.hashValue", @@ -943,6 +1076,15 @@ "tier": "swift-generated", "jsName": "hashValue" }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "path": "Precipitation.hash(into:)", + "kind": "instanceMethod", + "tier": "unsupported", + "reasons": [ + "inout-parameter" + ] + }, { "id": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO", "path": "Flavor.hash(into:)", diff --git a/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json b/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json index 4fe3324cf..3f25c0823 100644 --- a/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json +++ b/metadata-generator/tests/swift/snapshots/SwiftDemo.ir.json @@ -20,6 +20,7 @@ "s:9SwiftDemo5ShapeP", "s:9SwiftDemo7PolygonC", "s:9SwiftDemo6SquareC", + "s:9SwiftDemo13PrecipitationO", "s:9SwiftDemo10ShapeErrorO", "s:9SwiftDemo11MeasurementO", "s:9SwiftDemo4RingV", @@ -29,7 +30,13 @@ "s:9SwiftDemo16makeDefaultPointAA0E0VyF", "s:9SwiftDemo13defaultFlavorAA0D0Ovp", "s:9SwiftDemo13globalCounterSivp", - "s:9SwiftDemo11Coordinatesa" + "s:9SwiftDemo11Coordinatesa", + "s:9SwiftDemo11checkedSideyS2dKF", + "s:9SwiftDemo8echoInt8ys0D0VADF", + "s:9SwiftDemo10echoUInt64ys0D0VADF", + "s:9SwiftDemo10largestIntSiyF", + "s:9SwiftDemo5shoutySSSgACF", + "s:9SwiftDemo7TrackerC" ], "externalTypes": [ { @@ -202,7 +209,7 @@ "name": "ShapeError", "access": "public", "declaration": "enum ShapeError", - "location": "file://Sources/SwiftDemo/Shapes.swift:49:12", + "location": "file://Sources/SwiftDemo/Shapes.swift:54:12", "graph": "SwiftDemo.symbols.json", "members": [ "s:9SwiftDemo10ShapeErrorO11invalidSideyACSdcACmF", @@ -233,7 +240,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:50:9", + "location": "file://Sources/SwiftDemo/Shapes.swift:55:9", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo10ShapeErrorO" }, @@ -266,7 +273,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:51:9", + "location": "file://Sources/SwiftDemo/Shapes.swift:56:9", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo10ShapeErrorO" }, @@ -277,10 +284,53 @@ "name": "unknown", "access": "public", "declaration": "case unknown", - "location": "file://Sources/SwiftDemo/Shapes.swift:52:9", + "location": "file://Sources/SwiftDemo/Shapes.swift:57:9", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo10ShapeErrorO" }, + { + "id": "s:9SwiftDemo10echoUInt64ys0D0VADF", + "kind": "function", + "path": "echoUInt64(_:)", + "name": "echoUInt64(_:)", + "access": "public", + "declaration": "func echoUInt64(_ value: UInt64) -> UInt64", + "parameters": [ + { + "internalName": "value", + "type": { + "spelling": "UInt64", + "references": [ + "s:s6UInt64V" + ] + } + } + ], + "returns": { + "spelling": "UInt64", + "references": [ + "s:s6UInt64V" + ] + }, + "location": "file://Sources/SwiftDemo/Values.swift:9:12", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:9SwiftDemo10largestIntSiyF", + "kind": "function", + "path": "largestInt()", + "name": "largestInt()", + "access": "public", + "declaration": "func largestInt() -> Int", + "returns": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "location": "file://Sources/SwiftDemo/Values.swift:10:12", + "graph": "SwiftDemo.symbols.json" + }, { "id": "s:9SwiftDemo11Coordinatesa", "kind": "typeAlias", @@ -295,7 +345,7 @@ "s:Sd" ] }, - "location": "file://Sources/SwiftDemo/Shapes.swift:136:17", + "location": "file://Sources/SwiftDemo/Shapes.swift:141:17", "graph": "SwiftDemo.symbols.json" }, { @@ -305,7 +355,7 @@ "name": "Measurement", "access": "public", "declaration": "enum Measurement", - "location": "file://Sources/SwiftDemo/Shapes.swift:55:12", + "location": "file://Sources/SwiftDemo/Shapes.swift:60:12", "graph": "SwiftDemo.symbols.json", "members": [ "s:9SwiftDemo11MeasurementO6lengthyACSdcACmF", @@ -322,7 +372,7 @@ "name": "Unit", "access": "public", "declaration": "struct Unit", - "location": "file://Sources/SwiftDemo/Shapes.swift:60:18", + "location": "file://Sources/SwiftDemo/Shapes.swift:65:18", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO", "members": [ @@ -349,7 +399,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:62:15", + "location": "file://Sources/SwiftDemo/Shapes.swift:67:15", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO4UnitV" }, @@ -367,7 +417,7 @@ ] }, "settable": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:61:19", + "location": "file://Sources/SwiftDemo/Shapes.swift:66:19", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO4UnitV" }, @@ -400,7 +450,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:57:9", + "location": "file://Sources/SwiftDemo/Shapes.swift:62:9", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO" }, @@ -411,7 +461,7 @@ "name": "none", "access": "public", "declaration": "case none", - "location": "file://Sources/SwiftDemo/Shapes.swift:58:9", + "location": "file://Sources/SwiftDemo/Shapes.swift:63:9", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO" }, @@ -429,7 +479,7 @@ ] }, "settable": false, - "location": "file://Sources/SwiftDemo/Shapes.swift:65:15", + "location": "file://Sources/SwiftDemo/Shapes.swift:70:15", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO" }, @@ -450,10 +500,119 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:56:9", + "location": "file://Sources/SwiftDemo/Shapes.swift:61:9", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo11MeasurementO" }, + { + "id": "s:9SwiftDemo11checkedSideyS2dKF", + "kind": "function", + "path": "checkedSide(_:)", + "name": "checkedSide(_:)", + "access": "public", + "declaration": "func checkedSide(_ side: Double) throws -> Double", + "parameters": [ + { + "internalName": "side", + "type": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + } + } + ], + "returns": { + "spelling": "Double", + "references": [ + "s:Sd" + ] + }, + "throws": true, + "location": "file://Sources/SwiftDemo/Values.swift:3:12", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:9SwiftDemo13PrecipitationO", + "kind": "enum", + "path": "Precipitation", + "name": "Precipitation", + "access": "public", + "declaration": "enum Precipitation", + "location": "file://Sources/SwiftDemo/Shapes.swift:50:12", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo13PrecipitationO4rainyA2CmF", + "s:9SwiftDemo13PrecipitationO4snowyA2CmF", + "s:9SwiftDemo13PrecipitationO4noneyA2CmF", + "s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc", + "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo13PrecipitationO" + ], + "conformances": [ + "s:SH", + "s:SQ", + "s:SY" + ] + }, + { + "id": "s:9SwiftDemo13PrecipitationO4noneyA2CmF", + "kind": "enumCase", + "path": "Precipitation.none", + "name": "none", + "access": "public", + "declaration": "case none", + "location": "file://Sources/SwiftDemo/Shapes.swift:51:21", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO" + }, + { + "id": "s:9SwiftDemo13PrecipitationO4rainyA2CmF", + "kind": "enumCase", + "path": "Precipitation.rain", + "name": "rain", + "access": "public", + "declaration": "case rain", + "location": "file://Sources/SwiftDemo/Shapes.swift:51:9", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO" + }, + { + "id": "s:9SwiftDemo13PrecipitationO4snowyA2CmF", + "kind": "enumCase", + "path": "Precipitation.snow", + "name": "snow", + "access": "public", + "declaration": "case snow", + "location": "file://Sources/SwiftDemo/Shapes.swift:51:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO" + }, + { + "id": "s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc", + "kind": "initializer", + "path": "Precipitation.init(rawValue:)", + "name": "init(rawValue:)", + "access": "public", + "declaration": "init?(rawValue: String)", + "parameters": [ + { + "label": "rawValue", + "internalName": "rawValue", + "type": { + "spelling": "String", + "references": [ + "s:SS" + ] + } + } + ], + "failable": true, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO", + "sourceOrigin": "s:SY8rawValuexSg03RawB0Qz_tcfc" + }, { "id": "s:9SwiftDemo13defaultFlavorAA0D0Ovp", "kind": "variable", @@ -469,7 +628,7 @@ }, "settable": false, "let": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:134:11", + "location": "file://Sources/SwiftDemo/Shapes.swift:139:11", "graph": "SwiftDemo.symbols.json" }, { @@ -486,7 +645,7 @@ ] }, "settable": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:135:11", + "location": "file://Sources/SwiftDemo/Shapes.swift:140:11", "graph": "SwiftDemo.symbols.json" }, { @@ -502,7 +661,7 @@ "s:9SwiftDemo5PointV" ] }, - "location": "file://Sources/SwiftDemo/Shapes.swift:133:12", + "location": "file://Sources/SwiftDemo/Shapes.swift:138:12", "graph": "SwiftDemo.symbols.json" }, { @@ -512,7 +671,7 @@ "name": "Ring", "access": "public", "declaration": "struct Ring", - "location": "file://Sources/SwiftDemo/Shapes.swift:71:14", + "location": "file://Sources/SwiftDemo/Shapes.swift:76:14", "graph": "SwiftDemo.symbols.json", "members": [ "s:9SwiftDemo4RingV5innerAA5PointVvp", @@ -559,7 +718,7 @@ "s:9SwiftDemo4RingV" ] }, - "location": "file://Sources/SwiftDemo/Shapes.swift:85:23", + "location": "file://Sources/SwiftDemo/Shapes.swift:90:23", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo4RingV" }, @@ -592,7 +751,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:75:11", + "location": "file://Sources/SwiftDemo/Shapes.swift:80:11", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo4RingV" }, @@ -610,7 +769,7 @@ ] }, "settable": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:72:15", + "location": "file://Sources/SwiftDemo/Shapes.swift:77:15", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo4RingV" }, @@ -628,7 +787,7 @@ ] }, "settable": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:73:15", + "location": "file://Sources/SwiftDemo/Shapes.swift:78:15", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo4RingV" }, @@ -654,7 +813,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:80:25", + "location": "file://Sources/SwiftDemo/Shapes.swift:85:25", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo4RingV" }, @@ -853,6 +1012,33 @@ "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo5ShapeP" }, + { + "id": "s:9SwiftDemo5shoutySSSgACF", + "kind": "function", + "path": "shout(_:)", + "name": "shout(_:)", + "access": "public", + "declaration": "func shout(_ name: String?) -> String?", + "parameters": [ + { + "internalName": "name", + "type": { + "spelling": "String?", + "references": [ + "s:SS" + ] + } + } + ], + "returns": { + "spelling": "String?", + "references": [ + "s:SS" + ] + }, + "location": "file://Sources/SwiftDemo/Values.swift:11:12", + "graph": "SwiftDemo.symbols.json" + }, { "id": "s:9SwiftDemo6CanvasC", "kind": "class", @@ -866,7 +1052,7 @@ "modifiers": [ "final" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:101:19", + "location": "file://Sources/SwiftDemo/Shapes.swift:106:19", "graph": "SwiftDemo.symbols.json", "members": [ "s:9SwiftDemo6CanvasCACycfc", @@ -897,7 +1083,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:103:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:108:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6CanvasC" }, @@ -911,7 +1097,7 @@ "attributes": [ "@MainActor" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:102:11", + "location": "file://Sources/SwiftDemo/Shapes.swift:107:11", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6CanvasC" }, @@ -1021,7 +1207,7 @@ "modifiers": [ "final" ], - "location": "file://Sources/SwiftDemo/Shapes.swift:106:19", + "location": "file://Sources/SwiftDemo/Shapes.swift:111:19", "graph": "SwiftDemo.symbols.json", "members": [ "s:9SwiftDemo6LoaderCACycfc", @@ -1052,7 +1238,7 @@ "introduced": "16.0.0" } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:124:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:129:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1070,7 +1256,7 @@ "unconditionallyDeprecated": true } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:127:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:132:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1098,7 +1284,7 @@ ] } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:116:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:121:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1121,7 +1307,7 @@ } } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:117:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:122:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1151,7 +1337,7 @@ ] }, "throws": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:109:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:114:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1175,7 +1361,7 @@ } ], "async": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:111:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:116:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1206,7 +1392,7 @@ }, "async": true, "throws": true, - "location": "file://Sources/SwiftDemo/Shapes.swift:110:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:115:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1239,7 +1425,7 @@ "index": 0 } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:114:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:119:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1279,7 +1465,7 @@ "s:Si" ] }, - "location": "file://Sources/SwiftDemo/Shapes.swift:119:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:124:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1302,7 +1488,7 @@ "modifier": "inout" } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:121:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:126:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1321,7 +1507,7 @@ "renamed": "fetch(url:)" } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:130:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:135:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1361,7 +1547,7 @@ "rhsPrecise": "s:9SwiftDemo5ShapeP" } ], - "location": "file://Sources/SwiftDemo/Shapes.swift:113:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:118:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1372,7 +1558,7 @@ "name": "init()", "access": "public", "declaration": "init()", - "location": "file://Sources/SwiftDemo/Shapes.swift:107:11", + "location": "file://Sources/SwiftDemo/Shapes.swift:112:11", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo6LoaderC" }, @@ -1549,7 +1735,7 @@ "name": "Counter", "access": "public", "declaration": "actor Counter", - "location": "file://Sources/SwiftDemo/Shapes.swift:90:13", + "location": "file://Sources/SwiftDemo/Shapes.swift:95:13", "graph": "SwiftDemo.symbols.json", "members": [ "s:9SwiftDemo7CounterC5valueSivp", @@ -1584,7 +1770,7 @@ "s:SS" ] }, - "location": "file://Sources/SwiftDemo/Shapes.swift:97:28", + "location": "file://Sources/SwiftDemo/Shapes.swift:102:28", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo7CounterC" }, @@ -1602,7 +1788,7 @@ ] }, "settable": false, - "location": "file://Sources/SwiftDemo/Shapes.swift:91:28", + "location": "file://Sources/SwiftDemo/Shapes.swift:96:28", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo7CounterC" }, @@ -1619,7 +1805,7 @@ "s:Si" ] }, - "location": "file://Sources/SwiftDemo/Shapes.swift:93:16", + "location": "file://Sources/SwiftDemo/Shapes.swift:98:16", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo7CounterC" }, @@ -1630,7 +1816,7 @@ "name": "init()", "access": "public", "declaration": "init()", - "location": "file://Sources/SwiftDemo/Shapes.swift:92:11", + "location": "file://Sources/SwiftDemo/Shapes.swift:97:11", "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo7CounterC" }, @@ -1987,6 +2173,175 @@ "graph": "SwiftDemo.symbols.json", "parent": "s:9SwiftDemo7PolygonC" }, + { + "id": "s:9SwiftDemo7TrackerC", + "kind": "class", + "path": "Tracker", + "name": "Tracker", + "access": "public", + "declaration": "final class Tracker", + "modifiers": [ + "final" + ], + "location": "file://Sources/SwiftDemo/Values.swift:13:19", + "graph": "SwiftDemo.symbols.json", + "members": [ + "s:9SwiftDemo7TrackerC9liveCountSivpZ", + "s:9SwiftDemo7TrackerC2idSivp", + "s:9SwiftDemo7TrackerC2idACSi_tcfc", + "s:9SwiftDemo7TrackerC4sameACyF" + ] + }, + { + "id": "s:9SwiftDemo7TrackerC2idACSi_tcfc", + "kind": "initializer", + "path": "Tracker.init(id:)", + "name": "init(id:)", + "access": "public", + "declaration": "init(id: Int)", + "parameters": [ + { + "label": "id", + "internalName": "id", + "type": { + "spelling": "Int", + "references": [ + "s:Si" + ] + } + } + ], + "location": "file://Sources/SwiftDemo/Values.swift:17:11", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7TrackerC" + }, + { + "id": "s:9SwiftDemo7TrackerC2idSivp", + "kind": "instanceProperty", + "path": "Tracker.id", + "name": "id", + "access": "public", + "declaration": "let id: Int", + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "let": true, + "location": "file://Sources/SwiftDemo/Values.swift:15:15", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7TrackerC" + }, + { + "id": "s:9SwiftDemo7TrackerC4sameACyF", + "kind": "instanceMethod", + "path": "Tracker.same()", + "name": "same()", + "access": "public", + "declaration": "func same() -> Tracker", + "returns": { + "spelling": "Tracker", + "references": [ + "s:9SwiftDemo7TrackerC" + ] + }, + "location": "file://Sources/SwiftDemo/Values.swift:24:16", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7TrackerC" + }, + { + "id": "s:9SwiftDemo7TrackerC9liveCountSivpZ", + "kind": "typeProperty", + "path": "Tracker.liveCount", + "name": "liveCount", + "access": "public", + "declaration": "static var liveCount: Int { get }", + "modifiers": [ + "static" + ], + "static": true, + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "location": "file://Sources/SwiftDemo/Values.swift:14:35", + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo7TrackerC" + }, + { + "id": "s:9SwiftDemo8echoInt8ys0D0VADF", + "kind": "function", + "path": "echoInt8(_:)", + "name": "echoInt8(_:)", + "access": "public", + "declaration": "func echoInt8(_ value: Int8) -> Int8", + "parameters": [ + { + "internalName": "value", + "type": { + "spelling": "Int8", + "references": [ + "s:s4Int8V" + ] + } + } + ], + "returns": { + "spelling": "Int8", + "references": [ + "s:s4Int8V" + ] + }, + "location": "file://Sources/SwiftDemo/Values.swift:8:12", + "graph": "SwiftDemo.symbols.json" + }, + { + "id": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "kind": "operator", + "path": "Precipitation.!=(_:_:)", + "name": "!=(_:_:)", + "access": "public", + "declaration": "static func != (lhs: borrowing Self, rhs: borrowing Self) -> Bool", + "modifiers": [ + "static" + ], + "static": true, + "synthesized": true, + "parameters": [ + { + "internalName": "lhs", + "type": { + "spelling": "Self" + }, + "modifier": "borrowing" + }, + { + "internalName": "rhs", + "type": { + "spelling": "Self" + }, + "modifier": "borrowing" + } + ], + "returns": { + "spelling": "Bool", + "references": [ + "s:Sb" + ] + }, + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol" + }, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO", + "sourceOrigin": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ" + }, { "id": "s:SQsRi_zRi0_zrlE2neoiySbx_xtFZ::SYNTHESIZED::s:9SwiftDemo6FlavorO", "kind": "operator", @@ -2051,6 +2406,43 @@ "graph": "SwiftDemo@Swift.symbols.json", "parent": "s:SS" }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "kind": "instanceProperty", + "path": "Precipitation.hashValue", + "name": "hashValue", + "access": "public", + "declaration": "var hashValue: Int { get }", + "synthesized": true, + "valueType": { + "spelling": "Int", + "references": [ + "s:Si" + ] + }, + "settable": false, + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol", + "constraints": [ + { + "kind": "conformance", + "lhs": "Self", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + }, + { + "kind": "conformance", + "lhs": "Self.RawValue", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ] + }, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO", + "sourceOrigin": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp" + }, { "id": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO", "kind": "instanceProperty", @@ -2088,6 +2480,63 @@ "parent": "s:9SwiftDemo6FlavorO", "sourceOrigin": "s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp" }, + { + "id": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo13PrecipitationO", + "kind": "instanceMethod", + "path": "Precipitation.hash(into:)", + "name": "hash(into:)", + "access": "public", + "declaration": "func hash(into hasher: inout Hasher)", + "synthesized": true, + "parameters": [ + { + "label": "into", + "internalName": "hasher", + "type": { + "spelling": "Hasher", + "references": [ + "s:s6HasherV" + ] + }, + "modifier": "inout" + } + ], + "genericConstraints": [ + { + "kind": "conformance", + "lhs": "Self", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + }, + { + "kind": "conformance", + "lhs": "Self.RawValue", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ], + "extension": { + "extendedModule": "Swift", + "typeKind": "swift.protocol", + "constraints": [ + { + "kind": "conformance", + "lhs": "Self", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + }, + { + "kind": "conformance", + "lhs": "Self.RawValue", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ] + }, + "graph": "SwiftDemo.symbols.json", + "parent": "s:9SwiftDemo13PrecipitationO", + "sourceOrigin": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF" + }, { "id": "s:SYsSHRzSH8RawValueSYRpzrlE4hash4intoys6HasherVz_tF::SYNTHESIZED::s:9SwiftDemo6FlavorO", "kind": "instanceMethod", diff --git a/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift b/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift index c714e7153..0888be6dc 100644 --- a/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift +++ b/metadata-generator/tests/swift/snapshots/SwiftDemo.probe.swift @@ -26,229 +26,305 @@ func __nsProbe4() { let _: SwiftDemo.Demo = SwiftDemo.Demo() } +// s:9SwiftDemo10echoUInt64ys0D0VADF +func __nsProbe5(_ a0: UInt64) { + let _: UInt64 = SwiftDemo.`echoUInt64`(a0) +} + +// s:9SwiftDemo10largestIntSiyF +func __nsProbe6() { + let _: Int = SwiftDemo.`largestInt`() +} + +// s:9SwiftDemo11checkedSideyS2dKF +func __nsProbe7(_ a0: Double) throws { + let _: Double = try SwiftDemo.`checkedSide`(a0) +} + +// s:9SwiftDemo13PrecipitationO +func __nsProbe8(_ value: SwiftDemo.Precipitation) -> SwiftDemo.Precipitation { value } + +// s:9SwiftDemo13PrecipitationO4noneyA2CmF +func __nsProbe9() { + let _: SwiftDemo.Precipitation = SwiftDemo.Precipitation.`none` +} + +// s:9SwiftDemo13PrecipitationO4rainyA2CmF +func __nsProbe10() { + let _: SwiftDemo.Precipitation = SwiftDemo.Precipitation.`rain` +} + +// s:9SwiftDemo13PrecipitationO4snowyA2CmF +func __nsProbe11() { + let _: SwiftDemo.Precipitation = SwiftDemo.Precipitation.`snow` +} + +// s:9SwiftDemo13PrecipitationO8rawValueACSgSS_tcfc +func __nsProbe12(_ a0: String) { + let _: SwiftDemo.Precipitation? = SwiftDemo.Precipitation(rawValue: a0) +} + // s:9SwiftDemo13defaultFlavorAA0D0Ovp -func __nsProbe5() { +func __nsProbe13() { let _: SwiftDemo.Flavor = SwiftDemo.`defaultFlavor` } // s:9SwiftDemo13globalCounterSivp -func __nsProbe6(_ newValue: Int) { +func __nsProbe14(_ newValue: Int) { let _: Int = SwiftDemo.`globalCounter` SwiftDemo.`globalCounter` = newValue } // s:9SwiftDemo16makeDefaultPointAA0E0VyF -func __nsProbe7() { +func __nsProbe15() { let _: SwiftDemo.Point = SwiftDemo.`makeDefaultPoint`() } // s:9SwiftDemo4RingV -func __nsProbe8(_ value: SwiftDemo.Ring) -> SwiftDemo.Ring { value } +func __nsProbe16(_ value: SwiftDemo.Ring) -> SwiftDemo.Ring { value } // s:9SwiftDemo4RingV5inner5outerAcA5PointV_AGtcfc -func __nsProbe9(_ a0: SwiftDemo.Point, _ a1: SwiftDemo.Point) { +func __nsProbe17(_ a0: SwiftDemo.Point, _ a1: SwiftDemo.Point) { let _: SwiftDemo.Ring = SwiftDemo.Ring(inner: a0, outer: a1) } // s:9SwiftDemo4RingV5innerAA5PointVvp -func __nsProbe10(_ receiver: inout SwiftDemo.Ring, _ newValue: SwiftDemo.Point) { +func __nsProbe18(_ receiver: inout SwiftDemo.Ring, _ newValue: SwiftDemo.Point) { let _: SwiftDemo.Point = receiver.`inner` receiver.`inner` = newValue } // s:9SwiftDemo4RingV5outerAA5PointVvp -func __nsProbe11(_ receiver: inout SwiftDemo.Ring, _ newValue: SwiftDemo.Point) { +func __nsProbe19(_ receiver: inout SwiftDemo.Ring, _ newValue: SwiftDemo.Point) { let _: SwiftDemo.Point = receiver.`outer` receiver.`outer` = newValue } // s:9SwiftDemo4RingV6expand2byySd_tF -func __nsProbe12(_ receiver: inout SwiftDemo.Ring, _ a0: Double) { +func __nsProbe20(_ receiver: inout SwiftDemo.Ring, _ a0: Double) { let _: Void = receiver.`expand`(by: a0) } // s:9SwiftDemo5PointV -func __nsProbe13(_ value: SwiftDemo.Point) -> SwiftDemo.Point { value } +func __nsProbe21(_ value: SwiftDemo.Point) -> SwiftDemo.Point { value } // s:9SwiftDemo5PointV11descriptionSSvp -func __nsProbe14(_ receiver: SwiftDemo.Point) { +func __nsProbe22(_ receiver: SwiftDemo.Point) { let _: String = receiver.`description` } // s:9SwiftDemo5PointV1x1yACSd_Sdtcfc -func __nsProbe15(_ a0: Double, _ a1: Double) { +func __nsProbe23(_ a0: Double, _ a1: Double) { let _: SwiftDemo.Point = SwiftDemo.Point(x: a0, y: a1) } // s:9SwiftDemo5PointV1xSdvp -func __nsProbe16(_ receiver: inout SwiftDemo.Point, _ newValue: Double) { +func __nsProbe24(_ receiver: inout SwiftDemo.Point, _ newValue: Double) { let _: Double = receiver.`x` receiver.`x` = newValue } // s:9SwiftDemo5PointV1ySdvp -func __nsProbe17(_ receiver: inout SwiftDemo.Point, _ newValue: Double) { +func __nsProbe25(_ receiver: inout SwiftDemo.Point, _ newValue: Double) { let _: Double = receiver.`y` receiver.`y` = newValue } // s:9SwiftDemo5PointV6lengthSdvp -func __nsProbe18(_ receiver: SwiftDemo.Point) { +func __nsProbe26(_ receiver: SwiftDemo.Point) { let _: Double = receiver.`length` } +// s:9SwiftDemo5shoutySSSgACF +func __nsProbe27(_ a0: String?) { + let _: String? = SwiftDemo.`shout`(a0) +} + // s:9SwiftDemo6CanvasC -func __nsProbe19(_ value: SwiftDemo.Canvas) -> SwiftDemo.Canvas { value } +func __nsProbe28(_ value: SwiftDemo.Canvas) -> SwiftDemo.Canvas { value } // s:9SwiftDemo6FlavorO -func __nsProbe20(_ value: SwiftDemo.Flavor) -> SwiftDemo.Flavor { value } +func __nsProbe29(_ value: SwiftDemo.Flavor) -> SwiftDemo.Flavor { value } // s:9SwiftDemo6FlavorO11descriptionSSvp -func __nsProbe21(_ receiver: SwiftDemo.Flavor) { +func __nsProbe30(_ receiver: SwiftDemo.Flavor) { let _: String = receiver.`description` } // s:9SwiftDemo6FlavorO7vanillayA2CmF -func __nsProbe22() { +func __nsProbe31() { let _: SwiftDemo.Flavor = SwiftDemo.Flavor.`vanilla` } // s:9SwiftDemo6FlavorO8rawValueACSgSi_tcfc -func __nsProbe23(_ a0: Int) { +func __nsProbe32(_ a0: Int) { let _: SwiftDemo.Flavor? = SwiftDemo.Flavor(rawValue: a0) } // s:9SwiftDemo6FlavorO9chocolateyA2CmF -func __nsProbe24() { +func __nsProbe33() { let _: SwiftDemo.Flavor = SwiftDemo.Flavor.`chocolate` } // s:9SwiftDemo6LoaderC -func __nsProbe25(_ value: SwiftDemo.Loader) -> SwiftDemo.Loader { value } +func __nsProbe34(_ value: SwiftDemo.Loader) -> SwiftDemo.Loader { value } // s:9SwiftDemo6LoaderC10modernOnlyyyF @available(iOS 16.0, *) -func __nsProbe26(_ receiver: SwiftDemo.Loader) { +func __nsProbe35(_ receiver: SwiftDemo.Loader) { let _: Void = receiver.`modernOnly`() } // s:9SwiftDemo6LoaderC11legacyFetchyyF -func __nsProbe27(_ receiver: SwiftDemo.Loader) { +func __nsProbe36(_ receiver: SwiftDemo.Loader) { let _: Void = receiver.`legacyFetch`() } // s:9SwiftDemo6LoaderC8oldFetchyyF -func __nsProbe28(_ receiver: SwiftDemo.Loader) { +func __nsProbe37(_ receiver: SwiftDemo.Loader) { let _: Void = receiver.`oldFetch`() } // s:9SwiftDemo6LoaderCACycfc -func __nsProbe29() { +func __nsProbe38() { let _: SwiftDemo.Loader = SwiftDemo.Loader() } // s:9SwiftDemo6SquareC -func __nsProbe30(_ value: SwiftDemo.Square) -> SwiftDemo.Square { value } +func __nsProbe39(_ value: SwiftDemo.Square) -> SwiftDemo.Square { value } // s:9SwiftDemo6SquareC4areaSdvp -func __nsProbe31(_ receiver: SwiftDemo.Square) { +func __nsProbe40(_ receiver: SwiftDemo.Square) { let _: Double = receiver.`area` } // s:9SwiftDemo6SquareC4sideACSd_tcfc -func __nsProbe32(_ a0: Double) { +func __nsProbe41(_ a0: Double) { let _: SwiftDemo.Square = SwiftDemo.Square(side: a0) } // s:9SwiftDemo6SquareC4sideSdvp -func __nsProbe33(_ receiver: SwiftDemo.Square, _ newValue: Double) { +func __nsProbe42(_ receiver: SwiftDemo.Square, _ newValue: Double) { let _: Double = receiver.`side` receiver.`side` = newValue } // s:9SwiftDemo6SquareC5greet4nameS2S_tF -func __nsProbe34(_ receiver: SwiftDemo.Square, _ a0: String) { +func __nsProbe43(_ receiver: SwiftDemo.Square, _ a0: String) { let _: String = receiver.`greet`(name: a0) } // s:9SwiftDemo6SquareC5scale2byySd_tF -func __nsProbe35(_ receiver: SwiftDemo.Square, _ a0: Double) { +func __nsProbe44(_ receiver: SwiftDemo.Square, _ a0: Double) { let _: Void = receiver.`scale`(by: a0) } // s:9SwiftDemo6SquareC5sidesSivpZ -func __nsProbe36() { +func __nsProbe45() { let _: Int = SwiftDemo.Square.`sides` } // s:9SwiftDemo7CounterC -func __nsProbe37(_ value: SwiftDemo.Counter) -> SwiftDemo.Counter { value } +func __nsProbe46(_ value: SwiftDemo.Counter) -> SwiftDemo.Counter { value } // s:9SwiftDemo7CounterC5labelSSyF -func __nsProbe38(_ receiver: SwiftDemo.Counter) { +func __nsProbe47(_ receiver: SwiftDemo.Counter) { let _: String = receiver.`label`() } // s:9SwiftDemo7CounterCACycfc -func __nsProbe39() { +func __nsProbe48() { let _: SwiftDemo.Counter = SwiftDemo.Counter() } // s:9SwiftDemo7PolygonC -func __nsProbe40(_ value: SwiftDemo.Polygon) -> SwiftDemo.Polygon { value } +func __nsProbe49(_ value: SwiftDemo.Polygon) -> SwiftDemo.Polygon { value } // s:9SwiftDemo7PolygonC11vertexCountSivp -func __nsProbe41(_ receiver: SwiftDemo.Polygon) { +func __nsProbe50(_ receiver: SwiftDemo.Polygon) { let _: Int = receiver.`vertexCount` } // s:9SwiftDemo7PolygonC4makeACyFZ -func __nsProbe42() { +func __nsProbe51() { let _: SwiftDemo.Polygon = SwiftDemo.Polygon.`make`() } // s:9SwiftDemo7PolygonC4name11vertexCountACSS_Sitcfc -func __nsProbe43(_ a0: String, _ a1: Int) { +func __nsProbe52(_ a0: String, _ a1: Int) { let _: SwiftDemo.Polygon = SwiftDemo.Polygon(name: a0, vertexCount: a1) } // s:9SwiftDemo7PolygonC4nameACSgSS_tcfc -func __nsProbe44(_ a0: String) { +func __nsProbe53(_ a0: String) { let _: SwiftDemo.Polygon? = SwiftDemo.Polygon(name: a0) } // s:9SwiftDemo7PolygonC4nameSSvp -func __nsProbe45(_ receiver: SwiftDemo.Polygon) { +func __nsProbe54(_ receiver: SwiftDemo.Polygon) { let _: String = receiver.`name` } // s:9SwiftDemo7PolygonC5scale1x1yySd_SdtF -func __nsProbe46(_ receiver: SwiftDemo.Polygon, _ a0: Double, _ a1: Double) { +func __nsProbe55(_ receiver: SwiftDemo.Polygon, _ a0: Double, _ a1: Double) { let _: Void = receiver.`scale`(x: a0, y: a1) } // s:9SwiftDemo7PolygonC5scale2byySd_tF -func __nsProbe47(_ receiver: SwiftDemo.Polygon, _ a0: Double) { +func __nsProbe56(_ receiver: SwiftDemo.Polygon, _ a0: Double) { let _: Void = receiver.`scale`(by: a0) } // s:9SwiftDemo7PolygonC5scale2byySi_tF -func __nsProbe48(_ receiver: SwiftDemo.Polygon, _ a0: Int) { +func __nsProbe57(_ receiver: SwiftDemo.Polygon, _ a0: Int) { let _: Void = receiver.`scale`(by: a0) } // s:9SwiftDemo7PolygonC6sharedACvpZ -func __nsProbe49() { +func __nsProbe58() { let _: SwiftDemo.Polygon = SwiftDemo.Polygon.`shared` } // s:9SwiftDemo7PolygonC8describeySSACSgFZ -func __nsProbe50(_ a0: SwiftDemo.Polygon?) { +func __nsProbe59(_ a0: SwiftDemo.Polygon?) { let _: String = SwiftDemo.Polygon.`describe`(a0) } +// s:9SwiftDemo7TrackerC +func __nsProbe60(_ value: SwiftDemo.Tracker) -> SwiftDemo.Tracker { value } + +// s:9SwiftDemo7TrackerC2idACSi_tcfc +func __nsProbe61(_ a0: Int) { + let _: SwiftDemo.Tracker = SwiftDemo.Tracker(id: a0) +} + +// s:9SwiftDemo7TrackerC2idSivp +func __nsProbe62(_ receiver: SwiftDemo.Tracker) { + let _: Int = receiver.`id` +} + +// s:9SwiftDemo7TrackerC4sameACyF +func __nsProbe63(_ receiver: SwiftDemo.Tracker) { + let _: SwiftDemo.Tracker = receiver.`same`() +} + +// s:9SwiftDemo7TrackerC9liveCountSivpZ +func __nsProbe64() { + let _: Int = SwiftDemo.Tracker.`liveCount` +} + +// s:9SwiftDemo8echoInt8ys0D0VADF +func __nsProbe65(_ a0: Int8) { + let _: Int8 = SwiftDemo.`echoInt8`(a0) +} + +// s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo13PrecipitationO +func __nsProbe66(_ receiver: SwiftDemo.Precipitation) { + let _: Int = receiver.`hashValue` +} + // s:SYsSHRzSH8RawValueSYRpzrlE04hashB0Sivp::SYNTHESIZED::s:9SwiftDemo6FlavorO -func __nsProbe51(_ receiver: SwiftDemo.Flavor) { +func __nsProbe67(_ receiver: SwiftDemo.Flavor) { let _: Int = receiver.`hashValue` } diff --git a/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts b/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts index 1b0ee7e15..575d20803 100644 --- a/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts +++ b/metadata-generator/tests/swift/snapshots/swift!SwiftDemo.d.ts @@ -1,16 +1,125 @@ -// Generated from Swift symbol graphs for module SwiftDemo. -// Type-only: no Swift members are callable from JavaScript yet. - -interface Greeter {} -declare class Demo {} -declare class Point {} -declare class Flavor {} -interface Shape {} -declare class Polygon {} -declare class Square {} -declare class ShapeError {} -declare class Measurement {} -declare class Ring {} -declare class Counter {} -declare class Canvas {} -declare class Loader {} +// Generated by objc-metadata-generator from the SwiftDemo symbol graphs. Do not edit. +// The JavaScript surface ns:swift exposes for SwiftDemo: every declaration is backed by a generated thunk. + +declare module "ns:swift/SwiftDemo" { + export class Demo { + constructor(); + greet(name: string, times: number | bigint): string; + greet(name: string): string; + "greet(name:times:)"(name: string, times: number | bigint): string; + "greet(name:)"(name: string): string; + static readonly version: string; + } + + export type Precipitation = "none" | "rain" | "snow"; + export const Precipitation: { + readonly none: "none"; + readonly rain: "rain"; + readonly snow: "snow"; + init(rawValue: string): Precipitation | null; + hashValue(value: Precipitation): number; + }; + + export class Ring { + constructor(inner: Point, outer: Point); + constructor(args: { inner: Point; outer: Point }); + inner: Point; + outer: Point; + expand(delta: number): void; + } + + export class Point { + constructor(x: number, y: number); + constructor(args: { x: number; y: number }); + readonly description: string; + x: number; + y: number; + readonly length: number; + } + + export class Canvas { + private constructor(); + } + + export type Flavor = "vanilla" | "chocolate"; + export const Flavor: { + description(value: Flavor): string; + readonly vanilla: "vanilla"; + init(rawValue: number | bigint): Flavor | null; + readonly chocolate: "chocolate"; + hashValue(value: Flavor): number; + }; + + export class Loader { + constructor(); + /** + * @remarks Requires iOS 16.0; throws on earlier versions. + */ + modernOnly(): void; + /** + * @deprecated Use fetch(url:) instead + */ + legacyFetch(): void; + /** + * @deprecated Renamed to `fetch(url:)`. + */ + oldFetch(): void; + } + + export class Square extends Polygon { + constructor(side: number); + constructor(args: { side: number }); + readonly area: number; + side: number; + greet(name: string): string; + scale(x: number, y: number): void; + "scale(by: Double)"(factor: number): void; + "scale(x:y:)"(x: number, y: number): void; + "scale(by: Int)"(factor: number | bigint): void; + static readonly sides: number; + } + + export class Counter { + constructor(); + label(): string; + } + + export class Polygon { + constructor(name: string, vertexCount: number | bigint); + constructor(args: { name: string; vertexCount: number | bigint }); + constructor(name: string); + constructor(args: { name: string }); + readonly vertexCount: number; + static make(): Polygon; + readonly name: string; + scale(x: number, y: number): void; + "scale(x:y:)"(x: number, y: number): void; + "scale(by: Double)"(factor: number): void; + "scale(by: Int)"(factor: number | bigint): void; + static readonly shared: Polygon; + static describe(polygon: Polygon | null | undefined): string; + } + + export class Tracker { + constructor(id: number | bigint); + constructor(args: { id: number | bigint }); + readonly id: number; + same(): Tracker; + static readonly liveCount: number; + } + + export function echoUInt64(value: number | bigint): number; + export function largestInt(): number; + export function checkedSide(side: number): number; + export const defaultFlavor: Flavor; + export let globalCounter: number; + export function makeDefaultPoint(): Point; + export function shout(name: string | null | undefined): string | null; + export function echoInt8(value: number | bigint): number; +} + +declare module "ns:swift" { + interface SwiftModules { + SwiftDemo: typeof import("ns:swift/SwiftDemo"); + } +} diff --git a/metadata-generator/tests/swift/typescript/usage.ts b/metadata-generator/tests/swift/typescript/usage.ts new file mode 100644 index 000000000..8cb9d3302 --- /dev/null +++ b/metadata-generator/tests/swift/typescript/usage.ts @@ -0,0 +1,30 @@ +// Type-checked by the TypeScriptUsageCompiles test against types/index.d.ts and +// the generated swift!SwiftDemo.d.ts snapshot. Every @ts-expect-error line +// must fail to compile: an unused directive is itself an error. +import * as swift from "ns:swift"; +import { Demo, Point, Flavor, Polygon, Square, Tracker, shout, globalCounter } from "ns:swift/SwiftDemo"; + +const SwiftDemo = swift.module("SwiftDemo"); +const demo: Demo = new SwiftDemo.Demo(); +const greeting: string = demo.greet("NativeScript"); +const twice: string = demo.greet("a", 2n); +const point = new Point({ x: 2, y: 3 }); +const x: number = point.x; +point.y = 4; +const flavor: Flavor = Flavor.init(1) ?? Flavor.vanilla; +const text: string = Flavor.description(flavor); +const square: Polygon = new Square(3); +square["scale(by: Int)"](2); +const maybe: string | null = shout(null); +const live: number = Tracker.liveCount; +const counter: number = globalCounter; + +// @ts-expect-error description is read-only +point.description = "x"; +// @ts-expect-error ambiguous overloads are not callable by base name +square.scale(2); +// @ts-expect-error Flavor is a union of case names +const bad: Flavor = "mint"; +// @ts-expect-error Canvas has no initializer callable from JavaScript +new SwiftDemo.Canvas(); +void [greeting, twice, x, text, maybe, live, counter, bad];