From 38fe989c6c1f224daa4b63b5638754f4f107b045 Mon Sep 17 00:00:00 2001 From: leogdion Date: Wed, 18 Jun 2025 10:54:56 -0400 Subject: [PATCH 01/10] Adding Macro Samples and More Capabilities (#64) --- .github/workflows/SyntaxKit.yml | 2 +- .swiftlint.yml | 1 + Macros/Options/.github/workflows/Options.yml | 242 ++++++++ Macros/Options/.gitignore | 133 +++++ Macros/Options/.gitrepo | 12 + Macros/Options/.hound.yml | 2 + Macros/Options/.periphery.yml | 1 + Macros/Options/.spi.yml | 4 + Macros/Options/.swift-version | 1 + Macros/Options/.swiftformat | 7 + Macros/Options/.swiftlint.yml | 118 ++++ Macros/Options/LICENSE | 22 + Macros/Options/Mintfile | 2 + Macros/Options/Package.swift | 34 ++ Macros/Options/Package@swift-5.10.swift | 65 +++ Macros/Options/Package@swift-6.1.swift | 54 ++ Macros/Options/README.md | 182 ++++++ Macros/Options/Scripts/docc.sh | 3 + Macros/Options/Scripts/gh-md-toc | 421 +++++++++++++ Macros/Options/Scripts/lint.sh | 44 ++ Macros/Options/Sources/Options/Array.swift | 58 ++ .../Sources/Options/CodingOptions.swift | 49 ++ .../Options/Sources/Options/Dictionary.swift | 51 ++ .../Documentation.docc/Documentation.md | 162 +++++ Macros/Options/Sources/Options/EnumSet.swift | 139 +++++ Macros/Options/Sources/Options/Macro.swift | 42 ++ .../Options/Sources/Options/MappedEnum.swift | 66 +++ .../MappedValueRepresentable+Codable.swift | 97 +++ .../Options/MappedValueRepresentable.swift | 68 +++ .../MappedValueRepresentableError.swift | 47 ++ .../Options/MappedValueRepresented.swift | 62 ++ .../Sources/Options/MappedValues.swift | 42 ++ .../OptionsMacros/Extensions/Array.swift | 42 ++ .../Extensions/ArrayExprSyntax.swift | 46 ++ .../Extensions/DeclModifierListSyntax.swift | 45 ++ .../Extensions/DeclModifierSyntax.swift | 41 ++ .../Extensions/DictionaryElementSyntax.swift | 50 ++ .../Extensions/DictionaryExprSyntax.swift | 44 ++ .../Extensions/EnumDeclSyntax.swift | 45 ++ .../Extensions/ExtensionDeclSyntax.swift | 59 ++ .../Extensions/InheritanceClauseSyntax.swift | 47 ++ .../OptionsMacros/Extensions/KeyValues.swift | 70 +++ .../Extensions/TypeAliasDeclSyntax.swift | 42 ++ .../Extensions/VariableDeclSyntax.swift | 84 +++ .../OptionsMacros/InvalidDeclError.swift | 35 ++ .../Sources/OptionsMacros/MacrosPlugin.swift | 39 ++ .../Sources/OptionsMacros/OptionsMacro.swift | 138 +++++ .../Tests/OptionsTests/EnumSetTests.swift | 90 +++ .../Tests/OptionsTests/MappedEnumTests.swift | 69 +++ ...appedValueCollectionRepresentedTests.swift | 157 +++++ ...appedValueDictionaryRepresentedTests.swift | 77 +++ .../MappedValueRepresentableTests.swift | 40 ++ .../Mocks/MockCollectionEnum.swift | 61 ++ .../Mocks/MockDictionaryEnum.swift | 58 ++ .../Tests/OptionsTests/Mocks/MockError.swift | 34 ++ Macros/Options/codecov.yml | 2 + Macros/Options/logo.png | Bin 0 -> 89318 bytes Macros/Options/logo.svg | 551 ++++++++++++++++++ Macros/Options/project.yml | 13 + Macros/SKSampleMacro/.gitignore | 8 + Macros/SKSampleMacro/Package.resolved | 15 + Macros/SKSampleMacro/Package.swift | 59 ++ .../Sources/SKSampleMacro/SKSampleMacro.swift | 11 + .../Sources/SKSampleMacroClient/main.swift | 8 + .../SKSampleMacroMacro.swift | 42 ++ .../SKSampleMacroTests.swift | 48 ++ Package.resolved | 2 +- Sources/SyntaxKit/CodeBlock+ExprSyntax.swift | 51 ++ Sources/SyntaxKit/Extension.swift | 96 +++ Sources/SyntaxKit/Infix.swift | 70 +++ Sources/SyntaxKit/Literal.swift | 49 ++ Sources/SyntaxKit/Tuple.swift | 71 +++ Sources/SyntaxKit/TypeAlias.swift | 65 +++ Sources/SyntaxKit/Variable.swift | 29 + Tests/SyntaxKitTests/ExtensionTests.swift | 180 ++++++ Tests/SyntaxKitTests/LiteralValueTests.swift | 111 ++++ .../OptionsMacroIntegrationTests.swift | 228 ++++++++ Tests/SyntaxKitTests/TypeAliasTests.swift | 176 ++++++ .../SyntaxKitTests/VariableStaticTests.swift | 154 +++++ project.yml | 4 + 80 files changed, 5687 insertions(+), 2 deletions(-) create mode 100644 Macros/Options/.github/workflows/Options.yml create mode 100644 Macros/Options/.gitignore create mode 100644 Macros/Options/.gitrepo create mode 100644 Macros/Options/.hound.yml create mode 100644 Macros/Options/.periphery.yml create mode 100644 Macros/Options/.spi.yml create mode 100644 Macros/Options/.swift-version create mode 100644 Macros/Options/.swiftformat create mode 100644 Macros/Options/.swiftlint.yml create mode 100644 Macros/Options/LICENSE create mode 100644 Macros/Options/Mintfile create mode 100644 Macros/Options/Package.swift create mode 100644 Macros/Options/Package@swift-5.10.swift create mode 100644 Macros/Options/Package@swift-6.1.swift create mode 100644 Macros/Options/README.md create mode 100755 Macros/Options/Scripts/docc.sh create mode 100755 Macros/Options/Scripts/gh-md-toc create mode 100755 Macros/Options/Scripts/lint.sh create mode 100644 Macros/Options/Sources/Options/Array.swift create mode 100644 Macros/Options/Sources/Options/CodingOptions.swift create mode 100644 Macros/Options/Sources/Options/Dictionary.swift create mode 100644 Macros/Options/Sources/Options/Documentation.docc/Documentation.md create mode 100644 Macros/Options/Sources/Options/EnumSet.swift create mode 100644 Macros/Options/Sources/Options/Macro.swift create mode 100644 Macros/Options/Sources/Options/MappedEnum.swift create mode 100644 Macros/Options/Sources/Options/MappedValueRepresentable+Codable.swift create mode 100644 Macros/Options/Sources/Options/MappedValueRepresentable.swift create mode 100644 Macros/Options/Sources/Options/MappedValueRepresentableError.swift create mode 100644 Macros/Options/Sources/Options/MappedValueRepresented.swift create mode 100644 Macros/Options/Sources/Options/MappedValues.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/Array.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/ArrayExprSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierListSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/DictionaryElementSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/DictionaryExprSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/EnumDeclSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/ExtensionDeclSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/InheritanceClauseSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/KeyValues.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/TypeAliasDeclSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/Extensions/VariableDeclSyntax.swift create mode 100644 Macros/Options/Sources/OptionsMacros/InvalidDeclError.swift create mode 100644 Macros/Options/Sources/OptionsMacros/MacrosPlugin.swift create mode 100644 Macros/Options/Sources/OptionsMacros/OptionsMacro.swift create mode 100644 Macros/Options/Tests/OptionsTests/EnumSetTests.swift create mode 100644 Macros/Options/Tests/OptionsTests/MappedEnumTests.swift create mode 100644 Macros/Options/Tests/OptionsTests/MappedValueCollectionRepresentedTests.swift create mode 100644 Macros/Options/Tests/OptionsTests/MappedValueDictionaryRepresentedTests.swift create mode 100644 Macros/Options/Tests/OptionsTests/MappedValueRepresentableTests.swift create mode 100644 Macros/Options/Tests/OptionsTests/Mocks/MockCollectionEnum.swift create mode 100644 Macros/Options/Tests/OptionsTests/Mocks/MockDictionaryEnum.swift create mode 100644 Macros/Options/Tests/OptionsTests/Mocks/MockError.swift create mode 100644 Macros/Options/codecov.yml create mode 100644 Macros/Options/logo.png create mode 100644 Macros/Options/logo.svg create mode 100644 Macros/Options/project.yml create mode 100644 Macros/SKSampleMacro/.gitignore create mode 100644 Macros/SKSampleMacro/Package.resolved create mode 100644 Macros/SKSampleMacro/Package.swift create mode 100644 Macros/SKSampleMacro/Sources/SKSampleMacro/SKSampleMacro.swift create mode 100644 Macros/SKSampleMacro/Sources/SKSampleMacroClient/main.swift create mode 100644 Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift create mode 100644 Macros/SKSampleMacro/Tests/SKSampleMacroTests/SKSampleMacroTests.swift create mode 100644 Sources/SyntaxKit/CodeBlock+ExprSyntax.swift create mode 100644 Sources/SyntaxKit/Extension.swift create mode 100644 Sources/SyntaxKit/Infix.swift create mode 100644 Sources/SyntaxKit/Tuple.swift create mode 100644 Sources/SyntaxKit/TypeAlias.swift create mode 100644 Tests/SyntaxKitTests/ExtensionTests.swift create mode 100644 Tests/SyntaxKitTests/LiteralValueTests.swift create mode 100644 Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift create mode 100644 Tests/SyntaxKitTests/TypeAliasTests.swift create mode 100644 Tests/SyntaxKitTests/VariableStaticTests.swift diff --git a/.github/workflows/SyntaxKit.yml b/.github/workflows/SyntaxKit.yml index dd72dfa..2c9de80 100644 --- a/.github/workflows/SyntaxKit.yml +++ b/.github/workflows/SyntaxKit.yml @@ -122,7 +122,7 @@ jobs: restore-keys: | ${{ runner.os }}-mint- - name: Install mint - if: steps.cache-mint.outputs.cache-hit != 'true' + if: steps.cache-mint.outputs.cache-hit == '' run: | git clone https://github.com/yonaskolb/Mint.git cd Mint diff --git a/.swiftlint.yml b/.swiftlint.yml index e4222bf..6236845 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -116,6 +116,7 @@ excluded: - .build - Mint - Examples + - Macros indentation_width: indentation_width: 2 file_name: diff --git a/Macros/Options/.github/workflows/Options.yml b/Macros/Options/.github/workflows/Options.yml new file mode 100644 index 0000000..1f13ac5 --- /dev/null +++ b/Macros/Options/.github/workflows/Options.yml @@ -0,0 +1,242 @@ +name: macOS +on: + push: + branches-ignore: + - '*WIP' +env: + PACKAGE_NAME: Options +jobs: + build-ubuntu: + name: Build on Ubuntu + env: + PACKAGE_NAME: Options + SWIFT_VER: ${{ matrix.swift-version }} + runs-on: ${{ matrix.runs-on }} + if: "!contains(github.event.head_commit.message, 'ci skip')" + strategy: + matrix: + runs-on: [ubuntu-20.04, ubuntu-22.04] + swift-version: ["5.7.1", "5.8.1", "5.9", "5.9.2", "5.10"] + steps: + - uses: actions/checkout@v4 + - name: Set Ubuntu Release DOT + run: echo "RELEASE_DOT=$(lsb_release -sr)" >> $GITHUB_ENV + - name: Set Ubuntu Release NUM + run: echo "RELEASE_NUM=${RELEASE_DOT//[-._]/}" >> $GITHUB_ENV + - name: Set Ubuntu Codename + run: echo "RELEASE_NAME=$(lsb_release -sc)" >> $GITHUB_ENV + - name: Cache swift package modules + id: cache-spm-linux + uses: actions/cache@v4 + env: + cache-name: cache-spm + with: + path: .build + key: ${{ runner.os }}-${{ env.RELEASE_DOT }}-${{ env.cache-name }}-${{ matrix.swift-version }}-${{ hashFiles('Package.resolved') }} + restore-keys: | + ${{ runner.os }}-${{ env.RELEASE_DOT }}-${{ env.cache-name }}-${{ matrix.swift-version }}- + ${{ runner.os }}-${{ env.RELEASE_DOT }}-${{ env.cache-name }}- + - name: Cache swift + id: cache-swift-linux + uses: actions/cache@v4 + env: + cache-name: cache-swift + with: + path: swift-${{ env.SWIFT_VER }}-RELEASE-ubuntu${{ env.RELEASE_DOT }} + key: ${{ runner.os }}-${{ env.cache-name }}-${{ matrix.swift-version }}-${{ env.RELEASE_DOT }} + restore-keys: | + ${{ runner.os }}-${{ env.cache-name }}-${{ matrix.swift-version }}- + - name: Download Swift + if: steps.cache-swift-linux.outputs.cache-hit != 'true' + run: curl -O https://download.swift.org/swift-${SWIFT_VER}-release/ubuntu${RELEASE_NUM}/swift-${SWIFT_VER}-RELEASE/swift-${SWIFT_VER}-RELEASE-ubuntu${RELEASE_DOT}.tar.gz + - name: Extract Swift + if: steps.cache-swift-linux.outputs.cache-hit != 'true' + run: tar xzf swift-${SWIFT_VER}-RELEASE-ubuntu${RELEASE_DOT}.tar.gz + - name: Add Path + run: echo "$GITHUB_WORKSPACE/swift-${SWIFT_VER}-RELEASE-ubuntu${RELEASE_DOT}/usr/bin" >> $GITHUB_PATH + - name: Test + run: swift test --enable-code-coverage + - uses: sersoft-gmbh/swift-coverage-action@v4 + id: coverage-files + with: + fail-on-empty-output: true + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true + flags: swift-${{ matrix.swift-version }},ubuntu-${{ matrix.RELEASE_DOT }} + verbose: true + token: ${{ secrets.CODECOV_TOKEN }} + files: ${{ join(fromJSON(steps.coverage-files.outputs.files), ',') }} + build-macos: + name: Build on macOS + runs-on: ${{ matrix.os }} + if: "!contains(github.event.head_commit.message, 'ci skip')" + env: + PACKAGE_NAME: Options + strategy: + matrix: + include: + - xcode: "/Applications/Xcode_14.1.app" + os: macos-12 + iOSVersion: "16.1" + watchOSVersion: "9.0" + watchName: "Apple Watch Series 5 - 40mm" + iPhoneName: "iPhone 12 mini" + - xcode: "/Applications/Xcode_14.2.app" + os: macos-12 + iOSVersion: "16.2" + watchOSVersion: "9.1" + watchName: "Apple Watch Ultra (49mm)" + iPhoneName: "iPhone 14" + - xcode: "/Applications/Xcode_15.0.1.app" + os: macos-13 + iOSVersion: "17.0.1" + watchOSVersion: "10.0" + watchName: "Apple Watch Series 9 (41mm)" + iPhoneName: "iPhone 15" + - xcode: "/Applications/Xcode_15.1.app" + os: macos-13 + iOSVersion: "17.2" + watchOSVersion: "10.2" + watchName: "Apple Watch Series 9 (45mm)" + iPhoneName: "iPhone 15 Plus" + - xcode: "/Applications/Xcode_15.2.app" + os: macos-14 + iOSVersion: "17.2" + watchOSVersion: "10.2" + watchName: "Apple Watch Ultra (49mm)" + iPhoneName: "iPhone 15 Pro" + - xcode: "/Applications/Xcode_15.3.app" + os: macos-14 + iOSVersion: "17.4" + watchOSVersion: "10.4" + watchName: "Apple Watch Ultra 2 (49mm)" + iPhoneName: "iPhone 15 Pro Max" + steps: + - uses: actions/checkout@v4 + - name: Cache swift package modules + id: cache-spm-macos + uses: actions/cache@v4 + env: + cache-name: cache-spm + with: + path: .build + key: ${{ matrix.os }}-build-${{ env.cache-name }}-${{ matrix.xcode }}-${{ hashFiles('Package.resolved') }} + restore-keys: | + ${{ matrix.os }}-build-${{ env.cache-name }}-${{ matrix.xcode }}- + - name: Cache mint + if: startsWith(matrix.xcode,'/Applications/Xcode_15.3') + id: cache-mint + uses: actions/cache@v4 + env: + cache-name: cache-mint + with: + path: .mint + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('Mintfile') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Set Xcode Name + run: echo "XCODE_NAME=$(basename -- ${{ matrix.xcode }} | sed 's/\.[^.]*$//' | cut -d'_' -f2)" >> $GITHUB_ENV + - name: Setup Xcode + run: sudo xcode-select -s ${{ matrix.xcode }}/Contents/Developer + - name: Install mint + if: startsWith(matrix.xcode,'/Applications/Xcode_15.3') + run: | + brew update + brew install mint + - name: Build + run: swift build + - name: Run Swift Package tests + run: swift test --enable-code-coverage + - uses: sersoft-gmbh/swift-coverage-action@v4 + id: coverage-files-spm + with: + fail-on-empty-output: true + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4 + with: + files: ${{ join(fromJSON(steps.coverage-files-spm.outputs.files), ',') }} + token: ${{ secrets.CODECOV_TOKEN }} + flags: macOS,${{ env.XCODE_NAME }},${{ matrix.runs-on }} + - name: Clean up spm build directory + run: rm -rf .build + - name: Lint + run: ./scripts/lint.sh + if: startsWith(matrix.xcode,'/Applications/Xcode_15.3') + # - name: Run iOS target tests + # run: xcodebuild test -scheme ${{ env.PACKAGE_NAME }} -sdk "iphonesimulator" -destination 'platform=iOS Simulator,name=${{ matrix.iPhoneName }},OS=${{ matrix.iOSVersion }}' -enableCodeCoverage YES build test + # - uses: sersoft-gmbh/swift-coverage-action@v4 + # id: coverage-files-iOS + # with: + # fail-on-empty-output: true + # - name: Upload coverage to Codecov + # uses: codecov/codecov-action@v4 + # with: + # fail_ci_if_error: true + # verbose: true + # token: ${{ secrets.CODECOV_TOKEN }} + # files: ${{ join(fromJSON(steps.coverage-files-iOS.outputs.files), ',') }} + # flags: iOS,iOS${{ matrix.iOSVersion }},macOS,${{ env.XCODE_NAME }} + # - name: Run watchOS target tests + # run: xcodebuild test -scheme ${{ env.PACKAGE_NAME }} -sdk "watchsimulator" -destination 'platform=watchOS Simulator,name=${{ matrix.watchName }},OS=${{ matrix.watchOSVersion }}' -enableCodeCoverage YES build test + # - uses: sersoft-gmbh/swift-coverage-action@v4 + # id: coverage-files-watchOS + # with: + # fail-on-empty-output: true + # - name: Upload coverage to Codecov + # uses: codecov/codecov-action@v4 + # with: + # fail_ci_if_error: true + # verbose: true + # token: ${{ secrets.CODECOV_TOKEN }} + # files: ${{ join(fromJSON(steps.coverage-files-watchOS.outputs.files), ',') }} + # flags: watchOS,watchOS${{ matrix.watchOSVersion }},macOS,${{ env.XCODE_NAME }} + build-self: + name: Build on Self-Hosting macOS + runs-on: [self-hosted, macOS] + if: github.event.repository.owner.login == github.event.organization.login && !contains(github.event.head_commit.message, 'ci skip') + steps: + - uses: actions/checkout@v4 + - name: Cache swift package modules + id: cache-spm-macos + uses: actions/cache@v4 + env: + cache-name: cache-spm + with: + path: .build + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('Package.resolved') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Cache mint + id: cache-mint + uses: actions/cache@v4 + env: + cache-name: cache-mint + with: + path: .mint + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('Mintfile') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Build + run: swift build + - name: Run Swift Package tests + run: swift test --enable-code-coverage + - uses: sersoft-gmbh/swift-coverage-action@v4 + with: + fail-on-empty-output: true + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + flags: macOS,${{ env.XCODE_NAME }} + - name: Clean up spm build directory + run: rm -rf .build + - name: Lint + run: ./scripts/lint.sh diff --git a/Macros/Options/.gitignore b/Macros/Options/.gitignore new file mode 100644 index 0000000..008465e --- /dev/null +++ b/Macros/Options/.gitignore @@ -0,0 +1,133 @@ +# Created by https://www.toptal.com/developers/gitignore/api/swift,swiftpm,swiftpackagemanager,xcode,macos +# Edit at https://www.toptal.com/developers/gitignore?templates=swift,swiftpm,swiftpackagemanager,xcode,macos + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +*.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +.swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +.mint +Output + +# Due to support for 5.10 and below +Package.resolved \ No newline at end of file diff --git a/Macros/Options/.gitrepo b/Macros/Options/.gitrepo new file mode 100644 index 0000000..394e5c2 --- /dev/null +++ b/Macros/Options/.gitrepo @@ -0,0 +1,12 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme +; +[subrepo] + remote = git@github.com:brightdigit/Options.git + branch = syntaxkit-sample + commit = a2fd9e31d5fdf1a0e9d61fe76ab5a4461d10b08a + parent = 12b377f8e1df18994e1c9693f6c6399e7f9ddeb2 + method = merge + cmdver = 0.4.9 diff --git a/Macros/Options/.hound.yml b/Macros/Options/.hound.yml new file mode 100644 index 0000000..6941f63 --- /dev/null +++ b/Macros/Options/.hound.yml @@ -0,0 +1,2 @@ +swiftlint: + config_file: .swiftlint.yml diff --git a/Macros/Options/.periphery.yml b/Macros/Options/.periphery.yml new file mode 100644 index 0000000..85b884a --- /dev/null +++ b/Macros/Options/.periphery.yml @@ -0,0 +1 @@ +retain_public: true diff --git a/Macros/Options/.spi.yml b/Macros/Options/.spi.yml new file mode 100644 index 0000000..2c312f8 --- /dev/null +++ b/Macros/Options/.spi.yml @@ -0,0 +1,4 @@ +version: 1 +builder: + configs: + - documentation_targets: [Options] diff --git a/Macros/Options/.swift-version b/Macros/Options/.swift-version new file mode 100644 index 0000000..760606e --- /dev/null +++ b/Macros/Options/.swift-version @@ -0,0 +1 @@ +5.7 diff --git a/Macros/Options/.swiftformat b/Macros/Options/.swiftformat new file mode 100644 index 0000000..c510d49 --- /dev/null +++ b/Macros/Options/.swiftformat @@ -0,0 +1,7 @@ +--indent 2 +--header "\n .*?\.swift\n SimulatorServices\n\n Created by Leo Dion.\n Copyright © {year} BrightDigit.\n\n Permission is hereby granted, free of charge, to any person\n obtaining a copy of this software and associated documentation\n files (the “Software”), to deal in the Software without\n restriction, including without limitation the rights to use,\n copy, modify, merge, publish, distribute, sublicense, and/or\n sell copies of the Software, and to permit persons to whom the\n Software is furnished to do so, subject to the following\n conditions:\n \n The above copyright notice and this permission notice shall be\n included in all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,\n EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n OTHER DEALINGS IN THE SOFTWARE.\n" +--commas inline +--disable wrapMultilineStatementBraces, redundantInternal +--extensionacl on-declarations +--decimalgrouping 3,4 +--exclude .build, DerivedData, .swiftpm diff --git a/Macros/Options/.swiftlint.yml b/Macros/Options/.swiftlint.yml new file mode 100644 index 0000000..6be46e8 --- /dev/null +++ b/Macros/Options/.swiftlint.yml @@ -0,0 +1,118 @@ +opt_in_rules: + - array_init + - attributes + - closure_body_length + - closure_end_indentation + - closure_spacing + - collection_alignment + - conditional_returns_on_newline + - contains_over_filter_count + - contains_over_filter_is_empty + - contains_over_first_not_nil + - contains_over_range_nil_comparison + - convenience_type + - discouraged_object_literal + - discouraged_optional_boolean + - empty_collection_literal + - empty_count + - empty_string + - empty_xctest_method + - enum_case_associated_values_count + - expiring_todo + - explicit_acl + - explicit_init + - explicit_top_level_acl + - fallthrough + - fatal_error_message + - file_name + - file_name_no_space + - file_types_order + - first_where + - flatmap_over_map_reduce + - force_unwrapping + - function_default_parameter_at_end + - ibinspectable_in_extension + - identical_operands + - implicit_return + - implicitly_unwrapped_optional + - indentation_width + - joined_default_parameter + - last_where + - legacy_multiple + - legacy_random + - literal_expression_end_indentation + - lower_acl_than_parent + - missing_docs + - modifier_order + - multiline_arguments + - multiline_arguments_brackets + - multiline_function_chains + - multiline_literal_brackets + - multiline_parameters + - nimble_operator + - nslocalizedstring_key + - nslocalizedstring_require_bundle + - number_separator + - object_literal + - operator_usage_whitespace + - optional_enum_case_matching + - overridden_super_call + - override_in_extension + - pattern_matching_keywords + - prefer_self_type_over_type_of_self + - prefer_zero_over_explicit_init + - private_action + - private_outlet + - prohibited_interface_builder + - prohibited_super_call + - quick_discouraged_call + - quick_discouraged_focused_test + - quick_discouraged_pending_test + - reduce_into + - redundant_nil_coalescing + - redundant_type_annotation + - required_enum_case + - single_test_class + - sorted_first_last + - sorted_imports + - static_operator + - strong_iboutlet + - toggle_bool + - trailing_closure + - type_contents_order + - unavailable_function + - unneeded_parentheses_in_closure_argument + - unowned_variable_capture + - untyped_error_in_catch + - vertical_parameter_alignment_on_call + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - xct_specific_matcher + - yoda_condition +analyzer_rules: + - explicit_self + - unused_declaration + - unused_import +type_body_length: + - 100 + - 200 +file_length: + - 200 + - 300 +function_body_length: + - 18 + - 40 +function_parameter_count: 8 +line_length: + - 90 + - 90 +identifier_name: + excluded: + - id +excluded: + - Tests + - DerivedData + - .build + - .swiftpm +indentation_width: + indentation_width: 2 diff --git a/Macros/Options/LICENSE b/Macros/Options/LICENSE new file mode 100644 index 0000000..59f9701 --- /dev/null +++ b/Macros/Options/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2020 Bright Digit, LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Macros/Options/Mintfile b/Macros/Options/Mintfile new file mode 100644 index 0000000..c1dc548 --- /dev/null +++ b/Macros/Options/Mintfile @@ -0,0 +1,2 @@ +nicklockwood/SwiftFormat@0.53.5 +realm/SwiftLint@0.54.0 \ No newline at end of file diff --git a/Macros/Options/Package.swift b/Macros/Options/Package.swift new file mode 100644 index 0000000..5646b68 --- /dev/null +++ b/Macros/Options/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version: 5.7.1 + +// swiftlint:disable explicit_top_level_acl +// swiftlint:disable prefixed_toplevel_constant +// swiftlint:disable explicit_acl + +import PackageDescription + +let package = Package( + name: "Options", + products: [ + .library( + name: "Options", + targets: ["Options"] + ) + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + ], + targets: [ + .target( + name: "Options", + dependencies: [] + ), + .testTarget( + name: "OptionsTests", + dependencies: ["Options"] + ) + ] +) + +// swiftlint:enable explicit_top_level_acl +// swiftlint:enable prefixed_toplevel_constant +// swiftlint:enable explicit_acl diff --git a/Macros/Options/Package@swift-5.10.swift b/Macros/Options/Package@swift-5.10.swift new file mode 100644 index 0000000..da62733 --- /dev/null +++ b/Macros/Options/Package@swift-5.10.swift @@ -0,0 +1,65 @@ +// swift-tools-version: 5.10 + +// swiftlint:disable explicit_top_level_acl +// swiftlint:disable prefixed_toplevel_constant +// swiftlint:disable explicit_acl + +import CompilerPluginSupport +import PackageDescription + +let swiftSettings = [ + SwiftSetting.enableUpcomingFeature("BareSlashRegexLiterals"), + SwiftSetting.enableUpcomingFeature("ConciseMagicFile"), + SwiftSetting.enableUpcomingFeature("ExistentialAny"), + SwiftSetting.enableUpcomingFeature("ForwardTrailingClosures"), + SwiftSetting.enableUpcomingFeature("ImplicitOpenExistentials"), + SwiftSetting.enableUpcomingFeature("StrictConcurrency"), + SwiftSetting.enableUpcomingFeature("DisableOutwardActorInference"), + SwiftSetting.enableExperimentalFeature("StrictConcurrency") +] + +let package = Package( + name: "Options", + platforms: [ + .macOS(.v10_15), + .iOS(.v13), + .tvOS(.v13), + .watchOS(.v6), + .macCatalyst(.v13), + .visionOS(.v1) + ], + products: [ + .library( + name: "Options", + targets: ["Options"] + ) + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-syntax", from: "510.0.0") + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0") + ], + targets: [ + .target( + name: "Options", + dependencies: ["OptionsMacros"], + swiftSettings: swiftSettings + ), + .macro( + name: "OptionsMacros", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax") + ], + swiftSettings: swiftSettings + ), + .testTarget( + name: "OptionsTests", + dependencies: ["Options"] + ) + ] +) + +// swiftlint:enable explicit_top_level_acl +// swiftlint:enable prefixed_toplevel_constant +// swiftlint:enable explicit_acl diff --git a/Macros/Options/Package@swift-6.1.swift b/Macros/Options/Package@swift-6.1.swift new file mode 100644 index 0000000..402bd68 --- /dev/null +++ b/Macros/Options/Package@swift-6.1.swift @@ -0,0 +1,54 @@ +// swift-tools-version: 6.1 + +// swiftlint:disable explicit_top_level_acl +// swiftlint:disable prefixed_toplevel_constant +// swiftlint:disable explicit_acl + +import CompilerPluginSupport +import PackageDescription + + +let package = Package( + name: "Options", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .watchOS(.v6), + .tvOS(.v13), + .visionOS(.v1) + ], + products: [ + .library( + name: "Options", + targets: ["Options"] + ) + ], + dependencies: [ + .package(path: "../.."), + .package(url: "https://github.com/apple/swift-syntax.git", from: "601.0.1") + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0") + ], + targets: [ + .target( + name: "Options", + dependencies: ["OptionsMacros"] + ), + .macro( + name: "OptionsMacros", + dependencies: [ + .product(name: "SyntaxKit", package: "SyntaxKit"), + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax") + ] + ), + .testTarget( + name: "OptionsTests", + dependencies: ["Options"] + ) + ] +) + +// swiftlint:enable explicit_top_level_acl +// swiftlint:enable prefixed_toplevel_constant +// swiftlint:enable explicit_acl diff --git a/Macros/Options/README.md b/Macros/Options/README.md new file mode 100644 index 0000000..40ed2ed --- /dev/null +++ b/Macros/Options/README.md @@ -0,0 +1,182 @@ + +

+ Options +

+

Options

+ +More powerful options for `Enum` and `OptionSet` types. + +[![SwiftPM](https://img.shields.io/badge/SPM-Linux%20%7C%20iOS%20%7C%20macOS%20%7C%20watchOS%20%7C%20tvOS-success?logo=swift)](https://swift.org) +[![Twitter](https://img.shields.io/badge/twitter-@brightdigit-blue.svg?style=flat)](http://twitter.com/brightdigit) +![GitHub](https://img.shields.io/github/license/brightdigit/Options) +![GitHub issues](https://img.shields.io/github/issues/brightdigit/Options) +![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/brightdigit/Options/Options.yml?label=actions&logo=github&?branch=main) + +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fbrightdigit%2FOptions%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/brightdigit/Options) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fbrightdigit%2FOptions%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/brightdigit/Options) + +[![Codecov](https://img.shields.io/codecov/c/github/brightdigit/Options)](https://codecov.io/gh/brightdigit/Options) +[![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/brightdigit/Options)](https://www.codefactor.io/repository/github/brightdigit/Options) +[![codebeat badge](https://codebeat.co/badges/c47b7e58-867c-410b-80c5-57e10140ba0f)](https://codebeat.co/projects/github-com-brightdigit-mistkit-main) +[![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/brightdigit/Options)](https://codeclimate.com/github/brightdigit/Options) +[![Code Climate technical debt](https://img.shields.io/codeclimate/tech-debt/brightdigit/Options?label=debt)](https://codeclimate.com/github/brightdigit/Options) +[![Code Climate issues](https://img.shields.io/codeclimate/issues/brightdigit/Options)](https://codeclimate.com/github/brightdigit/Options) +[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) + + +# Table of Contents + + * [Introduction](#introduction) + * [Requirements](#requirements) + * [Installation](#installation) + * [Usage](#usage) + * [Versatile Options with Enums and OptionSets](#versatile-options-with-enums-and-optionsets) + * [Multiple Value Types](#multiple-value-types) + * [Creating an OptionSet](#creating-an-optionset) + * [Further Code Documentation](#further-code-documentation) + * [License](#license) + +# Introduction + +**Options** provides a powerful set of features for `Enum` and `OptionSet` types: + +- Providing additional representations for `Enum` types besides the `RawType rawValue` +- Being able to interchange between `Enum` and `OptionSet` types +- Using an additional value type for a `Codable` `OptionSet` + +# Requirements + +**Apple Platforms** + +- Xcode 14.1 or later +- Swift 5.7.1 or later +- iOS 16 / watchOS 9 / tvOS 16 / macOS 12 or later deployment targets + +**Linux** + +- Ubuntu 20.04 or later +- Swift 5.7.1 or later + +# Installation + +Use the Swift Package Manager to install this library via the repository url: + +``` +https://github.com/brightdigit/Options.git +``` + +Use version up to `1.0`. + +# Usage + +## Versatile Options + +Let's say we are using an `Enum` for a list of popular social media networks: + +```swift +enum SocialNetwork : Int { + case digg + case aim + case bebo + case delicious + case eworld + case googleplus + case itunesping + case jaiku + case miiverse + case musically + case orkut + case posterous + case stumbleupon + case windowslive + case yahoo +} +``` + +We'll be using this as a way to define a particular social handle: + +```swift +struct SocialHandle { + let name : String + let network : SocialNetwork +} +``` + +However we also want to provide a way to have a unique set of social networks available: + +```swift +struct SocialNetworkSet : Int, OptionSet { +... +} + +let user : User +let networks : SocialNetworkSet = user.availableNetworks() +``` + +We can then simply use ``Options()`` macro to generate both these types: + +```swift +@Options +enum SocialNetwork : Int { + case digg + case aim + case bebo + case delicious + case eworld + case googleplus + case itunesping + case jaiku + case miiverse + case musically + case orkut + case posterous + case stumbleupon + case windowslive + case yahoo +} +``` + +Now we can use the newly create `SocialNetworkSet` type to store a set of values: + +```swift +let networks : SocialNetworkSet +networks = [.aim, .delicious, .googleplus, .windowslive] +``` + +## Multiple Value Types + +With the ``Options()`` macro, we add the ability to encode and decode values not only from their raw value but also from a another type such as a string. This is useful for when you want to store the values in JSON format. + +For instance, with a type like `SocialNetwork` we need need to store the value as an Integer: + +```json +5 +``` + +However by adding the ``Options()`` macro we can also decode from a String: + +``` +"googleplus" +``` + +## Creating an OptionSet + +We can also have a new `OptionSet` type created. ``Options()`` create a new `OptionSet` type with the suffix `-Set`. This new `OptionSet` will automatically work with your enum to create a distinct set of values. Additionally it will decode and encode your values as an Array of String. This means the value: + +```swift +[.aim, .delicious, .googleplus, .windowslive] +``` + +is encoded as: + +```json +["aim", "delicious", "googleplus", "windowslive"] +``` + +# Further Code Documentation + +[Documentation Here](https://swiftpackageindex.com/brightdigit/Options/main/documentation/options) + +# License + +This code is distributed under the MIT license. See the [LICENSE](LICENSE) file for more info. diff --git a/Macros/Options/Scripts/docc.sh b/Macros/Options/Scripts/docc.sh new file mode 100755 index 0000000..3e4c918 --- /dev/null +++ b/Macros/Options/Scripts/docc.sh @@ -0,0 +1,3 @@ +#!/bin/sh +xcodebuild docbuild -scheme SimulatorServices -derivedDataPath DerivedData -destination 'platform=macOS' +$(xcrun --find docc) process-archive transform-for-static-hosting DerivedData/Build/Products/Debug/SimulatorServices.doccarchive --output-path Output \ No newline at end of file diff --git a/Macros/Options/Scripts/gh-md-toc b/Macros/Options/Scripts/gh-md-toc new file mode 100755 index 0000000..03b5ddd --- /dev/null +++ b/Macros/Options/Scripts/gh-md-toc @@ -0,0 +1,421 @@ +#!/usr/bin/env bash + +# +# Steps: +# +# 1. Download corresponding html file for some README.md: +# curl -s $1 +# +# 2. Discard rows where no substring 'user-content-' (github's markup): +# awk '/user-content-/ { ... +# +# 3.1 Get last number in each row like ' ... sitemap.js.*<\/h/)+2, RLENGTH-5) +# +# 5. Find anchor and insert it inside "(...)": +# substr($0, match($0, "href=\"[^\"]+?\" ")+6, RLENGTH-8) +# + +gh_toc_version="0.10.0" + +gh_user_agent="gh-md-toc v$gh_toc_version" + +# +# Download rendered into html README.md by its url. +# +# +gh_toc_load() { + local gh_url=$1 + + if type curl &>/dev/null; then + curl --user-agent "$gh_user_agent" -s "$gh_url" + elif type wget &>/dev/null; then + wget --user-agent="$gh_user_agent" -qO- "$gh_url" + else + echo "Please, install 'curl' or 'wget' and try again." + exit 1 + fi +} + +# +# Converts local md file into html by GitHub +# +# -> curl -X POST --data '{"text": "Hello world github/linguist#1 **cool**, and #1!"}' https://api.github.com/markdown +#

Hello world github/linguist#1 cool, and #1!

'" +gh_toc_md2html() { + local gh_file_md=$1 + local skip_header=$2 + + URL=https://api.github.com/markdown/raw + + if [ -n "$GH_TOC_TOKEN" ]; then + TOKEN=$GH_TOC_TOKEN + else + TOKEN_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" + if [ -f "$TOKEN_FILE" ]; then + TOKEN="$(cat "$TOKEN_FILE")" + fi + fi + if [ -n "${TOKEN}" ]; then + AUTHORIZATION="Authorization: token ${TOKEN}" + fi + + local gh_tmp_file_md=$gh_file_md + if [ "$skip_header" = "yes" ]; then + if grep -Fxq "" "$gh_src"; then + # cut everything before the toc + gh_tmp_file_md=$gh_file_md~~ + sed '1,//d' "$gh_file_md" > "$gh_tmp_file_md" + fi + fi + + # echo $URL 1>&2 + OUTPUT=$(curl -s \ + --user-agent "$gh_user_agent" \ + --data-binary @"$gh_tmp_file_md" \ + -H "Content-Type:text/plain" \ + -H "$AUTHORIZATION" \ + "$URL") + + rm -f "${gh_file_md}~~" + + if [ "$?" != "0" ]; then + echo "XXNetworkErrorXX" + fi + if [ "$(echo "${OUTPUT}" | awk '/API rate limit exceeded/')" != "" ]; then + echo "XXRateLimitXX" + else + echo "${OUTPUT}" + fi +} + + +# +# Is passed string url +# +gh_is_url() { + case $1 in + https* | http*) + echo "yes";; + *) + echo "no";; + esac +} + +# +# TOC generator +# +gh_toc(){ + local gh_src=$1 + local gh_src_copy=$1 + local gh_ttl_docs=$2 + local need_replace=$3 + local no_backup=$4 + local no_footer=$5 + local indent=$6 + local skip_header=$7 + + if [ "$gh_src" = "" ]; then + echo "Please, enter URL or local path for a README.md" + exit 1 + fi + + + # Show "TOC" string only if working with one document + if [ "$gh_ttl_docs" = "1" ]; then + + echo "Table of Contents" + echo "=================" + echo "" + gh_src_copy="" + + fi + + if [ "$(gh_is_url "$gh_src")" == "yes" ]; then + gh_toc_load "$gh_src" | gh_toc_grab "$gh_src_copy" "$indent" + if [ "${PIPESTATUS[0]}" != "0" ]; then + echo "Could not load remote document." + echo "Please check your url or network connectivity" + exit 1 + fi + if [ "$need_replace" = "yes" ]; then + echo + echo "!! '$gh_src' is not a local file" + echo "!! Can't insert the TOC into it." + echo + fi + else + local rawhtml + rawhtml=$(gh_toc_md2html "$gh_src" "$skip_header") + if [ "$rawhtml" == "XXNetworkErrorXX" ]; then + echo "Parsing local markdown file requires access to github API" + echo "Please make sure curl is installed and check your network connectivity" + exit 1 + fi + if [ "$rawhtml" == "XXRateLimitXX" ]; then + echo "Parsing local markdown file requires access to github API" + echo "Error: You exceeded the hourly limit. See: https://developer.github.com/v3/#rate-limiting" + TOKEN_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" + echo "or place GitHub auth token here: ${TOKEN_FILE}" + exit 1 + fi + local toc + toc=`echo "$rawhtml" | gh_toc_grab "$gh_src_copy" "$indent"` + echo "$toc" + if [ "$need_replace" = "yes" ]; then + if grep -Fxq "" "$gh_src" && grep -Fxq "" "$gh_src"; then + echo "Found markers" + else + echo "You don't have or in your file...exiting" + exit 1 + fi + local ts="<\!--ts-->" + local te="<\!--te-->" + local dt + dt=$(date +'%F_%H%M%S') + local ext=".orig.${dt}" + local toc_path="${gh_src}.toc.${dt}" + local toc_createdby="" + local toc_footer + toc_footer="" + # http://fahdshariff.blogspot.ru/2012/12/sed-mutli-line-replacement-between-two.html + # clear old TOC + sed -i"${ext}" "/${ts}/,/${te}/{//!d;}" "$gh_src" + # create toc file + echo "${toc}" > "${toc_path}" + if [ "${no_footer}" != "yes" ]; then + echo -e "\n${toc_createdby}\n${toc_footer}\n" >> "$toc_path" + fi + + # insert toc file + if ! sed --version > /dev/null 2>&1; then + sed -i "" "/${ts}/r ${toc_path}" "$gh_src" + else + sed -i "/${ts}/r ${toc_path}" "$gh_src" + fi + echo + if [ "${no_backup}" = "yes" ]; then + rm "$toc_path" "$gh_src$ext" + fi + echo "!! TOC was added into: '$gh_src'" + if [ -z "${no_backup}" ]; then + echo "!! Origin version of the file: '${gh_src}${ext}'" + echo "!! TOC added into a separate file: '${toc_path}'" + fi + echo + fi + fi +} + +# +# Grabber of the TOC from rendered html +# +# $1 - a source url of document. +# It's need if TOC is generated for multiple documents. +# $2 - number of spaces used to indent. +# +gh_toc_grab() { + + href_regex="/href=\"[^\"]+?\"/" + common_awk_script=' + modified_href = "" + split(href, chars, "") + for (i=1;i <= length(href); i++) { + c = chars[i] + res = "" + if (c == "+") { + res = " " + } else { + if (c == "%") { + res = "\\x" + } else { + res = c "" + } + } + modified_href = modified_href res + } + print sprintf("%*s", (level-1)*'"$2"', "") "* [" text "](" gh_url modified_href ")" + ' + if [ "`uname -s`" == "OS/390" ]; then + grepcmd="pcregrep -o" + echoargs="" + awkscript='{ + level = substr($0, 3, 1) + text = substr($0, match($0, /<\/span><\/a>[^<]*<\/h/)+11, RLENGTH-14) + href = substr($0, match($0, '$href_regex')+6, RLENGTH-7) + '"$common_awk_script"' + }' + else + grepcmd="grep -Eo" + echoargs="-e" + awkscript='{ + level = substr($0, 3, 1) + text = substr($0, match($0, /">.*<\/h/)+2, RLENGTH-5) + href = substr($0, match($0, '$href_regex')+6, RLENGTH-7) + '"$common_awk_script"' + }' + fi + + # if closed is on the new line, then move it on the prev line + # for example: + # was: The command foo1 + # + # became: The command foo1 + sed -e ':a' -e 'N' -e '$!ba' -e 's/\n<\/h/<\/h/g' | + + # Sometimes a line can start with . Fix that. + sed -e ':a' -e 'N' -e '$!ba' -e 's/\n//g' | sed 's/<\/code>//g' | + + # remove g-emoji + sed 's/]*[^<]*<\/g-emoji> //g' | + + # now all rows are like: + #

title

.. + # format result line + # * $0 - whole string + # * last element of each row: "/dev/null; then + $tool --version | head -n 1 + else + echo "not installed" + fi + done +} + +show_help() { + local app_name + app_name=$(basename "$0") + echo "GitHub TOC generator ($app_name): $gh_toc_version" + echo "" + echo "Usage:" + echo " $app_name [options] src [src] Create TOC for a README file (url or local path)" + echo " $app_name - Create TOC for markdown from STDIN" + echo " $app_name --help Show help" + echo " $app_name --version Show version" + echo "" + echo "Options:" + echo " --indent Set indent size. Default: 3." + echo " --insert Insert new TOC into original file. For local files only. Default: false." + echo " See https://github.com/ekalinin/github-markdown-toc/issues/41 for details." + echo " --no-backup Remove backup file. Set --insert as well. Default: false." + echo " --hide-footer Do not write date & author of the last TOC update. Set --insert as well. Default: false." + echo " --skip-header Hide entry of the topmost headlines. Default: false." + echo " See https://github.com/ekalinin/github-markdown-toc/issues/125 for details." + echo "" +} + +# +# Options handlers +# +gh_toc_app() { + local need_replace="no" + local indent=3 + + if [ "$1" = '--help' ] || [ $# -eq 0 ] ; then + show_help + return + fi + + if [ "$1" = '--version' ]; then + show_version + return + fi + + if [ "$1" = '--indent' ]; then + indent="$2" + shift 2 + fi + + if [ "$1" = "-" ]; then + if [ -z "$TMPDIR" ]; then + TMPDIR="/tmp" + elif [ -n "$TMPDIR" ] && [ ! -d "$TMPDIR" ]; then + mkdir -p "$TMPDIR" + fi + local gh_tmp_md + if [ "`uname -s`" == "OS/390" ]; then + local timestamp + timestamp=$(date +%m%d%Y%H%M%S) + gh_tmp_md="$TMPDIR/tmp.$timestamp" + else + gh_tmp_md=$(mktemp "$TMPDIR/tmp.XXXXXX") + fi + while read -r input; do + echo "$input" >> "$gh_tmp_md" + done + gh_toc_md2html "$gh_tmp_md" | gh_toc_grab "" "$indent" + return + fi + + if [ "$1" = '--insert' ]; then + need_replace="yes" + shift + fi + + if [ "$1" = '--no-backup' ]; then + need_replace="yes" + no_backup="yes" + shift + fi + + if [ "$1" = '--hide-footer' ]; then + need_replace="yes" + no_footer="yes" + shift + fi + + if [ "$1" = '--skip-header' ]; then + skip_header="yes" + shift + fi + + + for md in "$@" + do + echo "" + gh_toc "$md" "$#" "$need_replace" "$no_backup" "$no_footer" "$indent" "$skip_header" + done + + echo "" + echo "" +} + +# +# Entry point +# +gh_toc_app "$@" \ No newline at end of file diff --git a/Macros/Options/Scripts/lint.sh b/Macros/Options/Scripts/lint.sh new file mode 100755 index 0000000..31c3fa9 --- /dev/null +++ b/Macros/Options/Scripts/lint.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +if [ -z "$SRCROOT" ]; then + SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + PACKAGE_DIR="${SCRIPT_DIR}/.." +else + PACKAGE_DIR="${SRCROOT}" +fi + +if [ -z "$GITHUB_ACTION" ]; then + MINT_CMD="/opt/homebrew/bin/mint" +else + MINT_CMD="mint" +fi + +export MINT_PATH="$PACKAGE_DIR/.mint" +MINT_ARGS="-n -m $PACKAGE_DIR/Mintfile --silent" +MINT_RUN="$MINT_CMD run $MINT_ARGS" + +pushd $PACKAGE_DIR + +$MINT_CMD bootstrap -m Mintfile + +if [ "$LINT_MODE" == "NONE" ]; then + exit +elif [ "$LINT_MODE" == "STRICT" ]; then + SWIFTFORMAT_OPTIONS="" + SWIFTLINT_OPTIONS="--strict" +else + SWIFTFORMAT_OPTIONS="" + SWIFTLINT_OPTIONS="" +fi + +pushd $PACKAGE_DIR + +if [ -z "$CI" ]; then + $MINT_RUN swiftformat . + $MINT_RUN swiftlint --fix +fi + +$MINT_RUN swiftformat --lint $SWIFTFORMAT_OPTIONS . +$MINT_RUN swiftlint lint $SWIFTLINT_OPTIONS + +popd diff --git a/Macros/Options/Sources/Options/Array.swift b/Macros/Options/Sources/Options/Array.swift new file mode 100644 index 0000000..0c4db74 --- /dev/null +++ b/Macros/Options/Sources/Options/Array.swift @@ -0,0 +1,58 @@ +// +// Array.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +// swiftlint:disable:next line_length +@available(*, deprecated, renamed: "MappedValueGenericRepresented", message: "Use MappedValueGenericRepresented instead.") +public protocol MappedValueCollectionRepresented: MappedValueRepresented + where MappedValueType: Sequence {} + +extension Array: MappedValues where Element: Equatable {} + +extension Collection where Element: Equatable, Self: MappedValues { + /// Get the index based on the value passed. + /// - Parameter value: Value to search. + /// - Returns: Index found. + public func key(value: Element) throws -> Self.Index { + guard let index = firstIndex(of: value) else { + throw MappedValueRepresentableError.valueNotFound + } + + return index + } + + /// Gets the value based on the index. + /// - Parameter key: The index. + /// - Returns: The value at index. + public func value(key: Self.Index) throws -> Element { + guard key < endIndex, key >= startIndex else { + throw MappedValueRepresentableError.valueNotFound + } + return self[key] + } +} diff --git a/Macros/Options/Sources/Options/CodingOptions.swift b/Macros/Options/Sources/Options/CodingOptions.swift new file mode 100644 index 0000000..e26ad68 --- /dev/null +++ b/Macros/Options/Sources/Options/CodingOptions.swift @@ -0,0 +1,49 @@ +// +// CodingOptions.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// Options for how a ``MappedValueRepresentable`` type is encoding and decoded. +public struct CodingOptions: OptionSet, Sendable { + /// Allow decoding from String + public static let allowMappedValueDecoding: CodingOptions = .init(rawValue: 1) + + /// Encode the value as a String. + public static let encodeAsMappedValue: CodingOptions = .init(rawValue: 2) + + /// Default options. + public static let `default`: CodingOptions = + [.allowMappedValueDecoding, encodeAsMappedValue] + + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } +} diff --git a/Macros/Options/Sources/Options/Dictionary.swift b/Macros/Options/Sources/Options/Dictionary.swift new file mode 100644 index 0000000..a7a3b31 --- /dev/null +++ b/Macros/Options/Sources/Options/Dictionary.swift @@ -0,0 +1,51 @@ +// +// Dictionary.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +// swiftlint:disable:next line_length +@available(*, deprecated, renamed: "MappedValueGenericRepresented", message: "Use MappedValueGenericRepresented instead.") +public protocol MappedValueDictionaryRepresented: MappedValueRepresented + where MappedValueType == [Int: MappedType] {} + +extension Dictionary: MappedValues where Value: Equatable { + public func key(value: Value) throws -> Key { + let pair = first { $0.value == value } + guard let key = pair?.key else { + throw MappedValueRepresentableError.valueNotFound + } + + return key + } + + public func value(key: Key) throws -> Value { + guard let value = self[key] else { + throw MappedValueRepresentableError.valueNotFound + } + return value + } +} diff --git a/Macros/Options/Sources/Options/Documentation.docc/Documentation.md b/Macros/Options/Sources/Options/Documentation.docc/Documentation.md new file mode 100644 index 0000000..994798d --- /dev/null +++ b/Macros/Options/Sources/Options/Documentation.docc/Documentation.md @@ -0,0 +1,162 @@ +# ``Options`` + +More powerful options for `Enum` and `OptionSet` types. + +## Overview + +**Options** provides a powerful set of features for `Enum` and `OptionSet` types: + +- Providing additional representations for `Enum` types besides the `RawType rawValue` +- Being able to interchange between `Enum` and `OptionSet` types +- Using an additional value type for a `Codable` `OptionSet` + +### Requirements + +**Apple Platforms** + +- Xcode 14.1 or later +- Swift 5.7.1 or later +- iOS 16 / watchOS 9 / tvOS 16 / macOS 12 or later deployment targets + +**Linux** + +- Ubuntu 20.04 or later +- Swift 5.7.1 or later + +### Installation + +Use the Swift Package Manager to install this library via the repository url: + +``` +https://github.com/brightdigit/Options.git +``` + +Use version up to `1.0`. + +### Versatile Options + +Let's say we are using an `Enum` for a list of popular social media networks: + +```swift +enum SocialNetwork : Int { + case digg + case aim + case bebo + case delicious + case eworld + case googleplus + case itunesping + case jaiku + case miiverse + case musically + case orkut + case posterous + case stumbleupon + case windowslive + case yahoo +} +``` + +We'll be using this as a way to define a particular social handle: + +```swift +struct SocialHandle { + let name : String + let network : SocialNetwork +} +``` + +However we also want to provide a way to have a unique set of social networks available: + +```swift +struct SocialNetworkSet : Int, OptionSet { +... +} + +let user : User +let networks : SocialNetworkSet = user.availableNetworks() +``` + +We can then simply use ``Options()`` macro to generate both these types: + +```swift +@Options +enum SocialNetwork : Int { + case digg + case aim + case bebo + case delicious + case eworld + case googleplus + case itunesping + case jaiku + case miiverse + case musically + case orkut + case posterous + case stumbleupon + case windowslive + case yahoo +} +``` + +Now we can use the newly create `SocialNetworkSet` type to store a set of values: + +```swift +let networks : SocialNetworkSet +networks = [.aim, .delicious, .googleplus, .windowslive] +``` + +### Multiple Value Types + +With the ``Options()`` macro, we add the ability to encode and decode values not only from their raw value but also from a another type such as a string. This is useful for when you want to store the values in JSON format. + +For instance, with a type like `SocialNetwork` we need need to store the value as an Integer: + +```json +5 +``` + +However by adding the ``Options()`` macro we can also decode from a String: + +``` +"googleplus" +``` + +### Creating an OptionSet + +We can also have a new `OptionSet` type created. ``Options()`` create a new `OptionSet` type with the suffix `-Set`. This new `OptionSet` will automatically work with your enum to create a distinct set of values. Additionally it will decode and encode your values as an Array of String. This means the value: + +```swift +[.aim, .delicious, .googleplus, .windowslive] +``` + +is encoded as: + +```json +["aim", "delicious", "googleplus", "windowslive"] +``` + +## Topics + +### Options conformance + +- ``Options()`` +- ``MappedValueRepresentable`` +- ``MappedValueRepresented`` +- ``EnumSet`` + +### Advanced customization + +- ``CodingOptions`` +- ``MappedValues`` + +### Errors + +- ``MappedValueRepresentableError-2k4ki`` + +### Deprecated + +- ``MappedValueCollectionRepresented`` +- ``MappedValueDictionaryRepresented`` +- ``MappedEnum`` diff --git a/Macros/Options/Sources/Options/EnumSet.swift b/Macros/Options/Sources/Options/EnumSet.swift new file mode 100644 index 0000000..c2e447e --- /dev/null +++ b/Macros/Options/Sources/Options/EnumSet.swift @@ -0,0 +1,139 @@ +/// Generic struct for using Enums with `RawValue`. +/// +/// If you have an `enum` such as: +/// ```swift +/// @Options +/// enum SocialNetwork : Int { +/// case digg +/// case aim +/// case bebo +/// case delicious +/// case eworld +/// case googleplus +/// case itunesping +/// case jaiku +/// case miiverse +/// case musically +/// case orkut +/// case posterous +/// case stumbleupon +/// case windowslive +/// case yahoo +/// } +/// ``` +/// An ``EnumSet`` could be used to store multiple values as an `OptionSet`: +/// ```swift +/// let socialNetworks : EnumSet = +/// [.digg, .aim, .yahoo, .miiverse] +/// ``` +public struct EnumSet: + OptionSet, Sendable, ExpressibleByArrayLiteral + where EnumType.RawValue: FixedWidthInteger & Sendable { + public typealias RawValue = EnumType.RawValue + + /// Raw Value of the OptionSet + public let rawValue: RawValue + + /// Creates the EnumSet based on the `rawValue` + /// - Parameter rawValue: Integer raw value of the OptionSet + public init(rawValue: RawValue) { + self.rawValue = rawValue + } + + public init(arrayLiteral elements: EnumType...) { + self.init(values: elements) + } + + /// Creates the EnumSet based on the values in the array. + /// - Parameter values: Array of enum values. + public init(values: [EnumType]) { + let set = Set(values.map(\.rawValue)) + rawValue = Self.cumulativeValue(basedOnRawValues: set) + } + + internal static func cumulativeValue( + basedOnRawValues rawValues: Set) -> RawValue { + rawValues.map { 1 << $0 }.reduce(0, |) + } +} + +extension FixedWidthInteger { + fileprivate static var one: Self { + 1 + } +} + +extension EnumSet where EnumType: CaseIterable { + internal static func enums(basedOnRawValue rawValue: RawValue) -> [EnumType] { + let cases = EnumType.allCases.sorted { $0.rawValue < $1.rawValue } + var values = [EnumType]() + var current = rawValue + for item in cases { + guard current > 0 else { + break + } + let rawValue = RawValue.one << item.rawValue + if current & rawValue != .zero { + values.append(item) + current -= rawValue + } + } + return values + } + + /// Returns an array of the enum values based on the OptionSet + /// - Returns: Array for each value represented by the enum. + public func array() -> [EnumType] { + Self.enums(basedOnRawValue: rawValue) + } +} + +#if swift(>=5.9) + extension EnumSet: Codable + where EnumType: MappedValueRepresentable, EnumType.MappedType: Codable { + /// Decodes the EnumSet based on an Array of MappedTypes. + /// - Parameter decoder: Decoder which contains info as an array of MappedTypes. + public init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + let values = try container.decode([EnumType.MappedType].self) + let rawValues = try values.map(EnumType.rawValue(basedOn:)) + let set = Set(rawValues) + rawValue = Self.cumulativeValue(basedOnRawValues: set) + } + + /// Encodes the EnumSet based on an Array of MappedTypes. + /// - Parameter encoder: Encoder which will contain info as an array of MappedTypes. + public func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + let values = Self.enums(basedOnRawValue: rawValue) + let mappedValues = try values + .map(\.rawValue) + .map(EnumType.mappedValue(basedOn:)) + try container.encode(mappedValues) + } + } +#else + extension EnumSet: Codable + where EnumType: MappedValueRepresentable, EnumType.MappedType: Codable { + /// Decodes the EnumSet based on an Array of MappedTypes. + /// - Parameter decoder: Decoder which contains info as an array of MappedTypes. + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let values = try container.decode([EnumType.MappedType].self) + let rawValues = try values.map(EnumType.rawValue(basedOn:)) + let set = Set(rawValues) + rawValue = Self.cumulativeValue(basedOnRawValues: set) + } + + /// Encodes the EnumSet based on an Array of MappedTypes. + /// - Parameter encoder: Encoder which will contain info as an array of MappedTypes. + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + let values = Self.enums(basedOnRawValue: rawValue) + let mappedValues = try values + .map(\.rawValue) + .map(EnumType.mappedValue(basedOn:)) + try container.encode(mappedValues) + } + } +#endif diff --git a/Macros/Options/Sources/Options/Macro.swift b/Macros/Options/Sources/Options/Macro.swift new file mode 100644 index 0000000..ab7ff7b --- /dev/null +++ b/Macros/Options/Sources/Options/Macro.swift @@ -0,0 +1,42 @@ +// +// Macro.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +#if swift(>=5.10) + /// Sets an enumeration up to implement + /// ``MappedValueRepresentable`` and ``MappedValueRepresented``. + @attached( + extension, + conformances: MappedValueRepresentable, MappedValueRepresented, + names: named(MappedType), named(mappedValues) + ) + @attached(peer, names: suffixed(Set)) + public macro Options() = #externalMacro(module: "OptionsMacros", type: "OptionsMacro") +#endif diff --git a/Macros/Options/Sources/Options/MappedEnum.swift b/Macros/Options/Sources/Options/MappedEnum.swift new file mode 100644 index 0000000..9298ada --- /dev/null +++ b/Macros/Options/Sources/Options/MappedEnum.swift @@ -0,0 +1,66 @@ +/// A generic struct for enumerations which allow for additional values attached. +@available( + *, + deprecated, + renamed: "MappedValueRepresentable", + message: "Use `MappedValueRepresentable` with `CodingOptions`." +) +public struct MappedEnum: Codable, Sendable + where EnumType.MappedType: Codable { + /// Base Enumeraion value. + public let value: EnumType + + /// Creates an instance based on the base enumeration value. + /// - Parameter value: Base Enumeration value. + public init(value: EnumType) { + self.value = value + } +} + +#if swift(>=5.9) + extension MappedEnum { + /// Decodes the value based on the mapped value. + /// - Parameter decoder: Decoder. + public init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + let label = try container.decode(EnumType.MappedType.self) + let rawValue = try EnumType.rawValue(basedOn: label) + guard let value = EnumType(rawValue: rawValue) else { + assertionFailure("Every mappedValue should always return a valid rawValue.") + throw DecodingError.invalidRawValue(rawValue) + } + self.value = value + } + + /// Encodes the value based on the mapped value. + /// - Parameter encoder: Encoder. + public func encode(to encoder: any Encoder) throws { + let string = try EnumType.mappedValue(basedOn: value.rawValue) + var container = encoder.singleValueContainer() + try container.encode(string) + } + } +#else + extension MappedEnum { + /// Decodes the value based on the mapped value. + /// - Parameter decoder: Decoder. + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let label = try container.decode(EnumType.MappedType.self) + let rawValue = try EnumType.rawValue(basedOn: label) + guard let value = EnumType(rawValue: rawValue) else { + assertionFailure("Every mappedValue should always return a valid rawValue.") + throw DecodingError.invalidRawValue(rawValue) + } + self.value = value + } + + /// Encodes the value based on the mapped value. + /// - Parameter encoder: Encoder. + public func encode(to encoder: Encoder) throws { + let string = try EnumType.mappedValue(basedOn: value.rawValue) + var container = encoder.singleValueContainer() + try container.encode(string) + } + } +#endif diff --git a/Macros/Options/Sources/Options/MappedValueRepresentable+Codable.swift b/Macros/Options/Sources/Options/MappedValueRepresentable+Codable.swift new file mode 100644 index 0000000..550f7c6 --- /dev/null +++ b/Macros/Options/Sources/Options/MappedValueRepresentable+Codable.swift @@ -0,0 +1,97 @@ +// +// MappedValueRepresentable+Codable.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +extension DecodingError { + internal static func invalidRawValue(_ rawValue: some Any) -> DecodingError { + .dataCorrupted( + .init(codingPath: [], debugDescription: "Raw Value \(rawValue) is invalid.") + ) + } +} + +extension SingleValueDecodingContainer { + fileprivate func decodeAsRawValue() throws -> T + where T.RawValue: Decodable { + let rawValue = try decode(T.RawValue.self) + guard let value = T(rawValue: rawValue) else { + throw DecodingError.invalidRawValue(rawValue) + } + return value + } + + fileprivate func decodeAsMappedType() throws -> T + where T.RawValue: Decodable, T.MappedType: Decodable { + let mappedValues: T.MappedType + do { + mappedValues = try decode(T.MappedType.self) + } catch { + return try decodeAsRawValue() + } + + let rawValue = try T.rawValue(basedOn: mappedValues) + + guard let value = T(rawValue: rawValue) else { + assertionFailure("Every mappedValue should always return a valid rawValue.") + throw DecodingError.invalidRawValue(rawValue) + } + + return value + } +} + +extension MappedValueRepresentable + where Self: Decodable, MappedType: Decodable, RawValue: Decodable { + /// Decodes the type. + /// - Parameter decoder: Decoder. + public init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + + if Self.codingOptions.contains(.allowMappedValueDecoding) { + self = try container.decodeAsMappedType() + } else { + self = try container.decodeAsRawValue() + } + } +} + +extension MappedValueRepresentable + where Self: Encodable, MappedType: Encodable, RawValue: Encodable { + /// Encoding the type. + /// - Parameter decoder: Encodes. + public func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + if Self.codingOptions.contains(.encodeAsMappedValue) { + try container.encode(mappedValue()) + } else { + try container.encode(rawValue) + } + } +} diff --git a/Macros/Options/Sources/Options/MappedValueRepresentable.swift b/Macros/Options/Sources/Options/MappedValueRepresentable.swift new file mode 100644 index 0000000..896f4a9 --- /dev/null +++ b/Macros/Options/Sources/Options/MappedValueRepresentable.swift @@ -0,0 +1,68 @@ +// +// MappedValueRepresentable.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// An enum which has an additional value attached. +/// - Note: ``Options()`` macro will automatically set this up for you. +public protocol MappedValueRepresentable: RawRepresentable, CaseIterable, Sendable { + /// The additional value type. + associatedtype MappedType = String + + /// Options for how the enum should be decoded or encoded. + static var codingOptions: CodingOptions { + get + } + + /// Gets the raw value based on the MappedType. + /// - Parameter value: MappedType value. + /// - Returns: The raw value of the enumeration based on the `MappedType `value. + static func rawValue(basedOn string: MappedType) throws -> RawValue + + /// Gets the `MappedType` value based on the `rawValue`. + /// - Parameter rawValue: The raw value of the enumeration. + /// - Returns: The Mapped Type value based on the `rawValue`. + static func mappedValue(basedOn rawValue: RawValue) throws -> MappedType +} + +extension MappedValueRepresentable { + /// Options regarding how the type can be decoded or encoded. + public static var codingOptions: CodingOptions { + .default + } + + /// Gets the mapped value of the enumeration. + /// - Parameter rawValue: The raw value of the enumeration + /// which pretains to its index in the `mappedValues` Array. + /// - Throws: `MappedValueCollectionRepresentedError.valueNotFound` + /// if the raw value (i.e. index) is outside the range of the `mappedValues` array. + /// - Returns: + /// The Mapped Type value based on the value in the array at the raw value index. + public func mappedValue() throws -> MappedType { + try Self.mappedValue(basedOn: rawValue) + } +} diff --git a/Macros/Options/Sources/Options/MappedValueRepresentableError.swift b/Macros/Options/Sources/Options/MappedValueRepresentableError.swift new file mode 100644 index 0000000..d303174 --- /dev/null +++ b/Macros/Options/Sources/Options/MappedValueRepresentableError.swift @@ -0,0 +1,47 @@ +// +// MappedValueRepresentableError.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +// swiftlint:disable file_types_order +#if swift(>=5.10) + /// An Error thrown when the `MappedType` value or `RawType` value + /// are invalid for an `Enum`. + public enum MappedValueRepresentableError: Error, Sendable { + /// Whenever a value or key cannot be found. + case valueNotFound + } +#else + /// An Error thrown when the `MappedType` value or `RawType` value + /// are invalid for an `Enum`. + public enum MappedValueRepresentableError: Error { + case valueNotFound + } +#endif +// swiftlint:enable file_types_order diff --git a/Macros/Options/Sources/Options/MappedValueRepresented.swift b/Macros/Options/Sources/Options/MappedValueRepresented.swift new file mode 100644 index 0000000..26ef4e5 --- /dev/null +++ b/Macros/Options/Sources/Options/MappedValueRepresented.swift @@ -0,0 +1,62 @@ +// +// MappedValueRepresented.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// Protocol which simplifies ``MappedValueRepresentable``by using a ``MappedValues``. +public protocol MappedValueRepresented: MappedValueRepresentable + where MappedType: Equatable { + /// A object to lookup values and keys for mapped values. + associatedtype MappedValueType: MappedValues + /// An array of the mapped values which lines up with each case. + static var mappedValues: MappedValueType { get } +} + +extension MappedValueRepresented { + /// Gets the raw value based on the MappedType by finding the index of the mapped value. + /// - Parameter value: MappedType value. + /// - Throws: `MappedValueCollectionRepresentedError.valueNotFound` + /// If the value was not found in the array + /// - Returns: + /// The raw value of the enumeration + /// based on the index the MappedType value was found at. + public static func rawValue(basedOn value: MappedType) throws -> RawValue { + try mappedValues.key(value: value) + } + + /// Gets the mapped value based on the rawValue + /// by access the array at the raw value subscript. + /// - Parameter rawValue: The raw value of the enumeration + /// which pretains to its index in the `mappedValues` Array. + /// - Throws: `MappedValueCollectionRepresentedError.valueNotFound` + /// if the raw value (i.e. index) is outside the range of the `mappedValues` array. + /// - Returns: + /// The Mapped Type value based on the value in the array at the raw value index. + public static func mappedValue(basedOn rawValue: RawValue) throws -> MappedType { + try mappedValues.value(key: rawValue) + } +} diff --git a/Macros/Options/Sources/Options/MappedValues.swift b/Macros/Options/Sources/Options/MappedValues.swift new file mode 100644 index 0000000..67d0a45 --- /dev/null +++ b/Macros/Options/Sources/Options/MappedValues.swift @@ -0,0 +1,42 @@ +// +// MappedValues.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// Protocol which provides a method for ``MappedValueRepresented`` to pull values. +public protocol MappedValues { + /// Raw Value Type + associatedtype Value: Equatable + /// Key Value Type + associatedtype Key: Equatable + /// get the key vased on the value. + func key(value: Value) throws -> Key + /// get the value based on the key/index. + func value(key: Key) throws -> Value +} diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/Array.swift b/Macros/Options/Sources/OptionsMacros/Extensions/Array.swift new file mode 100644 index 0000000..78275fe --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/Array.swift @@ -0,0 +1,42 @@ +// +// Array.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +extension Array { + internal init?(keyValues: KeyValues) where Element == String { + self.init() + for key in 0 ..< keyValues.count { + guard let value = keyValues.get(key) else { + return nil + } + append(value) + } + } +} diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/ArrayExprSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/ArrayExprSyntax.swift new file mode 100644 index 0000000..20e52d7 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/ArrayExprSyntax.swift @@ -0,0 +1,46 @@ +// +// ArrayExprSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension ArrayExprSyntax { + internal init( + from items: some Collection, + _ closure: @escaping @Sendable (T) -> some ExprSyntaxProtocol + ) { + let values = items.map(closure).map { ArrayElementSyntax(expression: $0) } + let arrayElement = ArrayElementListSyntax { + .init(values) + } + self.init(elements: arrayElement) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierListSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierListSyntax.swift new file mode 100644 index 0000000..bc36764 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierListSyntax.swift @@ -0,0 +1,45 @@ +// +// DeclModifierListSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension DeclModifierListSyntax { + internal init(keywordModifier: Keyword?) { + if let keywordModifier { + self.init { + DeclModifierSyntax(name: .keyword(keywordModifier)) + } + } else { + self.init([]) + } + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierSyntax.swift new file mode 100644 index 0000000..49d781c --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/DeclModifierSyntax.swift @@ -0,0 +1,41 @@ +// +// DeclModifierSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +#if !canImport(SyntaxKit) +extension DeclModifierSyntax { + internal var isNeededAccessLevelModifier: Bool { + switch name.tokenKind { + case .keyword(.public): return true + default: return false + } + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/DictionaryElementSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/DictionaryElementSyntax.swift new file mode 100644 index 0000000..810087b --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/DictionaryElementSyntax.swift @@ -0,0 +1,50 @@ +// +// DictionaryElementSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension DictionaryElementSyntax { + internal init(pair: (key: Int, value: String)) { + self.init(key: pair.key, value: pair.value) + } + + internal init(key: Int, value: String) { + self.init( + key: IntegerLiteralExprSyntax(integerLiteral: key), + value: StringLiteralExprSyntax( + openingQuote: .stringQuoteToken(), + segments: .init([.stringSegment(.init(content: .stringSegment(value)))]), + closingQuote: .stringQuoteToken() + ) + ) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/DictionaryExprSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/DictionaryExprSyntax.swift new file mode 100644 index 0000000..025638d --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/DictionaryExprSyntax.swift @@ -0,0 +1,44 @@ +// +// DictionaryExprSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension DictionaryExprSyntax { + internal init(keyValues: KeyValues) { + let dictionaryElements = keyValues.dictionary.map(DictionaryElementSyntax.init(pair:)) + + let list = DictionaryElementListSyntax { + .init(dictionaryElements) + } + self.init(content: .elements(list)) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/EnumDeclSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/EnumDeclSyntax.swift new file mode 100644 index 0000000..9ca3717 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/EnumDeclSyntax.swift @@ -0,0 +1,45 @@ +// +// EnumDeclSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension EnumDeclSyntax { + internal var caseElements: [EnumCaseElementSyntax] { + memberBlock.members.flatMap { member in + guard let caseDecl = member.decl.as(EnumCaseDeclSyntax.self) else { + return [EnumCaseElementSyntax]() + } + + return Array(caseDecl.elements) + } + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/ExtensionDeclSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/ExtensionDeclSyntax.swift new file mode 100644 index 0000000..8f42eae --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/ExtensionDeclSyntax.swift @@ -0,0 +1,59 @@ +// +// ExtensionDeclSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +#if !canImport(SyntaxKit) +extension ExtensionDeclSyntax { + internal init( + enumDecl: EnumDeclSyntax, + conformingTo protocols: [SwiftSyntax.TypeSyntax] + ) throws { + let typeName = enumDecl.name + + let access = enumDecl.modifiers.first(where: \.isNeededAccessLevelModifier) + + let mappedValues = try VariableDeclSyntax.mappedValuesDeclarationForCases( + enumDecl.caseElements + ) + + self.init( + modifiers: DeclModifierListSyntax([access].compactMap { $0 }), + extendedType: IdentifierTypeSyntax(name: typeName), + inheritanceClause: InheritanceClauseSyntax(protocols: protocols), + memberBlock: MemberBlockSyntax( + members: MemberBlockItemListSyntax { + TypeAliasDeclSyntax(name: "MappedType", for: "String") + mappedValues + } + ) + ) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/InheritanceClauseSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/InheritanceClauseSyntax.swift new file mode 100644 index 0000000..84156e9 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/InheritanceClauseSyntax.swift @@ -0,0 +1,47 @@ +// +// InheritanceClauseSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension InheritanceClauseSyntax { + internal init(protocols: [SwiftSyntax.TypeSyntax]) { + self.init( + inheritedTypes: .init { + .init( + protocols.map { typeSyntax in + InheritedTypeSyntax(type: typeSyntax) + } + ) + } + ) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/KeyValues.swift b/Macros/Options/Sources/OptionsMacros/Extensions/KeyValues.swift new file mode 100644 index 0000000..7800a73 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/KeyValues.swift @@ -0,0 +1,70 @@ +// +// KeyValues.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +internal struct KeyValues { + internal private(set) var lastKey: Int? + internal private(set) var dictionary = [Int: String]() + + internal var count: Int { + dictionary.count + } + + internal var nextKey: Int { + (lastKey ?? -1) + 1 + } + + internal mutating func append(value: String, withKey key: Int? = nil) throws { + let key = key ?? nextKey + guard dictionary[key] == nil else { + throw InvalidDeclError.rawValue(key) + } + lastKey = key + dictionary[key] = value + } + + internal func get(_ key: Int) -> String? { + dictionary[key] + } +} + +extension KeyValues { + internal init(caseElements: [EnumCaseElementSyntax]) throws { + self.init() + for caseElement in caseElements { + let intText = caseElement.rawValue?.value + .as(IntegerLiteralExprSyntax.self)?.literal.text + let key = intText.flatMap { Int($0) } + let value = + caseElement.name.trimmed.text + try append(value: value, withKey: key) + } + } +} diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/TypeAliasDeclSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/TypeAliasDeclSyntax.swift new file mode 100644 index 0000000..f3e24b2 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/TypeAliasDeclSyntax.swift @@ -0,0 +1,42 @@ +// +// TypeAliasDeclSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension TypeAliasDeclSyntax { + internal init(name: TokenSyntax, for initializerTypeName: TokenSyntax) { + self.init( + name: name, + initializer: .init(value: IdentifierTypeSyntax(name: initializerTypeName)) + ) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/Extensions/VariableDeclSyntax.swift b/Macros/Options/Sources/OptionsMacros/Extensions/VariableDeclSyntax.swift new file mode 100644 index 0000000..9b221a6 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/Extensions/VariableDeclSyntax.swift @@ -0,0 +1,84 @@ +// +// VariableDeclSyntax.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + + +#if !canImport(SyntaxKit) +extension VariableDeclSyntax { + internal init( + keywordModifier: Keyword?, + bindingKeyword: Keyword, + variableName: String, + initializerExpression: (some ExprSyntaxProtocol)? + ) { + let modifiers = DeclModifierListSyntax(keywordModifier: keywordModifier) + + let initializer: InitializerClauseSyntax? = + initializerExpression.map { .init(value: $0) } + + self.init( + modifiers: modifiers, + bindingSpecifier: .keyword(bindingKeyword), + bindings: .init { + PatternBindingSyntax( + pattern: IdentifierPatternSyntax(identifier: .identifier(variableName)), + initializer: initializer + ) + } + ) + } + + internal static func initializerExpression( + from caseElements: [EnumCaseElementSyntax] + ) throws -> any ExprSyntaxProtocol { + let keyValues = try KeyValues(caseElements: caseElements) + if let array = Array(keyValues: keyValues) { + return ArrayExprSyntax(from: array) { value in + StringLiteralExprSyntax(content: value) + } + } else { + return DictionaryExprSyntax(keyValues: keyValues) + } + } + + internal static func mappedValuesDeclarationForCases( + _ caseElements: [EnumCaseElementSyntax] + ) throws -> VariableDeclSyntax { + let arrayExpression = try Self.initializerExpression(from: caseElements) + + return VariableDeclSyntax( + keywordModifier: .static, + bindingKeyword: .let, + variableName: "mappedValues", + initializerExpression: arrayExpression + ) + } +} +#endif diff --git a/Macros/Options/Sources/OptionsMacros/InvalidDeclError.swift b/Macros/Options/Sources/OptionsMacros/InvalidDeclError.swift new file mode 100644 index 0000000..ea31645 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/InvalidDeclError.swift @@ -0,0 +1,35 @@ +// +// InvalidDeclError.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +@preconcurrency import SwiftSyntax + +internal enum InvalidDeclError: Error, Sendable { + case kind(SyntaxKind) + case rawValue(Int) +} diff --git a/Macros/Options/Sources/OptionsMacros/MacrosPlugin.swift b/Macros/Options/Sources/OptionsMacros/MacrosPlugin.swift new file mode 100644 index 0000000..1bc8833 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/MacrosPlugin.swift @@ -0,0 +1,39 @@ +// +// MacrosPlugin.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftCompilerPlugin +import SwiftSyntax +import SwiftSyntaxMacros + +@main +internal struct MacrosPlugin: CompilerPlugin { + internal let providingMacros: [any Macro.Type] = [ + OptionsMacro.self + ] +} diff --git a/Macros/Options/Sources/OptionsMacros/OptionsMacro.swift b/Macros/Options/Sources/OptionsMacros/OptionsMacro.swift new file mode 100644 index 0000000..81c4e31 --- /dev/null +++ b/Macros/Options/Sources/OptionsMacros/OptionsMacro.swift @@ -0,0 +1,138 @@ +// +// OptionsMacro.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import SwiftSyntaxMacros + +#if canImport(SyntaxKit) +import SyntaxKit +public struct OptionsMacro: ExtensionMacro, PeerMacro { + public static func expansion(of node: SwiftSyntax.AttributeSyntax, attachedTo declaration: some SwiftSyntax.DeclGroupSyntax, providingExtensionsOf type: some SwiftSyntax.TypeSyntaxProtocol, conformingTo protocols: [SwiftSyntax.TypeSyntax], in context: some SwiftSyntaxMacros.MacroExpansionContext) throws -> [SwiftSyntax.ExtensionDeclSyntax] { + guard let enumDecl = declaration.as(EnumDeclSyntax.self) else { + throw InvalidDeclError.kind(declaration.kind) + } + + // Extract the type name + let typeName = enumDecl.name + + // Extract all EnumCaseElementSyntax from the enum + let caseElements: [EnumCaseElementSyntax] = enumDecl.memberBlock.members.flatMap { (member) -> [EnumCaseElementSyntax] in + guard let caseDecl = member.decl.as(EnumCaseDeclSyntax.self) else { + return [EnumCaseElementSyntax]() + } + return Array(caseDecl.elements) + } + + // Build mappedValues variable declaration (static let mappedValues = [...]) + // Check if any case has a raw value to determine if we need a dictionary + let hasRawValues = caseElements.contains { $0.rawValue != nil } + + let mappedValuesVariable: Variable + if hasRawValues { + let keyValues: [Int: String] = caseElements.reduce(into: [:]) { (result, element) in + guard let rawValue = element.rawValue?.value.as(IntegerLiteralExprSyntax.self)?.literal.text, + let key = Int(rawValue) else { + return + } + result[key] = element.name.trimmed.text + } + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues).static() + } else { + let caseNames: [String] = caseElements.map { element in + element.name.trimmed.text + } + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames).static() + } + + let extensionDecl = Extension(typeName.trimmed.text) { + TypeAlias("MappedType", equals: "String") + mappedValuesVariable + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + return [extensionDecl.syntax.as(ExtensionDeclSyntax.self)!] + + } + + public static func expansion(of node: SwiftSyntax.AttributeSyntax, providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol, in context: some SwiftSyntaxMacros.MacroExpansionContext) throws -> [SwiftSyntax.DeclSyntax] { + guard let enumDecl = declaration.as(EnumDeclSyntax.self) else { + throw InvalidDeclError.kind(declaration.kind) + } + + let typeName = enumDecl.name + let aliasName = "\(typeName.trimmed)Set" + let aliasDecl = TypeAlias(aliasName, equals: "EnumSet<\(typeName)>").syntax + + guard let declSyntax : DeclSyntax = DeclSyntax(aliasDecl.as(TypeAliasDeclSyntax.self)) else { + throw InvalidDeclError.kind(declaration.kind) + } + return [ + declSyntax + ] + } + +} +#else +public struct OptionsMacro: ExtensionMacro, PeerMacro { + public static func expansion( + of _: SwiftSyntax.AttributeSyntax, + providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol, + in _: some SwiftSyntaxMacros.MacroExpansionContext + ) throws -> [SwiftSyntax.DeclSyntax] { + guard let enumDecl = declaration.as(EnumDeclSyntax.self) else { + throw InvalidDeclError.kind(declaration.kind) + } + let typeName = enumDecl.name + + let aliasName: TokenSyntax = "\(typeName.trimmed)Set" + + let initializerName: TokenSyntax = "EnumSet<\(typeName)>" + + return [ + .init(TypeAliasDeclSyntax(name: aliasName, for: initializerName)) + ] + } + + public static func expansion( + of _: SwiftSyntax.AttributeSyntax, + attachedTo declaration: some SwiftSyntax.DeclGroupSyntax, + providingExtensionsOf _: some SwiftSyntax.TypeSyntaxProtocol, + conformingTo protocols: [SwiftSyntax.TypeSyntax], + in _: some SwiftSyntaxMacros.MacroExpansionContext + ) throws -> [SwiftSyntax.ExtensionDeclSyntax] { + guard let enumDecl = declaration.as(EnumDeclSyntax.self) else { + throw InvalidDeclError.kind(declaration.kind) + } + + let extensionDecl = try ExtensionDeclSyntax( + enumDecl: enumDecl, conformingTo: protocols + ) + return [extensionDecl] + } +} +#endif diff --git a/Macros/Options/Tests/OptionsTests/EnumSetTests.swift b/Macros/Options/Tests/OptionsTests/EnumSetTests.swift new file mode 100644 index 0000000..5e55439 --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/EnumSetTests.swift @@ -0,0 +1,90 @@ +// +// EnumSetTests.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +@testable import Options +import XCTest + +internal final class EnumSetTests: XCTestCase { + private static let text = "[\"a\",\"b\",\"c\"]" + + internal func testDecoder() { + // swiftlint:disable:next force_unwrapping + let data = Self.text.data(using: .utf8)! + let decoder = JSONDecoder() + let actual: EnumSet + do { + actual = try decoder.decode(EnumSet.self, from: data) + } catch { + XCTAssertNil(error) + return + } + XCTAssertEqual(actual.rawValue, 7) + } + + internal func testEncoder() { + let enumSet = EnumSet(values: [.a, .b, .c]) + let encoder = JSONEncoder() + let data: Data + do { + data = try encoder.encode(enumSet) + } catch { + XCTAssertNil(error) + return + } + + let dataText = String(bytes: data, encoding: .utf8) + + guard let text = dataText else { + XCTAssertNotNil(dataText) + return + } + + XCTAssertEqual(text, Self.text) + } + + internal func testInitValue() { + let set = EnumSet(rawValue: 7) + XCTAssertEqual(set.rawValue, 7) + } + + internal func testInitValues() { + let values: [MockCollectionEnum] = [.a, .b, .c] + let setA = EnumSet(values: values) + XCTAssertEqual(setA.rawValue, 7) + let setB: MockCollectionEnumSet = [.a, .b, .c] + XCTAssertEqual(setB.rawValue, 7) + } + + internal func testArray() { + let expected: [MockCollectionEnum] = [.b, .d] + let enumSet = EnumSet(values: expected) + let actual = enumSet.array() + XCTAssertEqual(actual, expected) + } +} diff --git a/Macros/Options/Tests/OptionsTests/MappedEnumTests.swift b/Macros/Options/Tests/OptionsTests/MappedEnumTests.swift new file mode 100644 index 0000000..1e19650 --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/MappedEnumTests.swift @@ -0,0 +1,69 @@ +// +// MappedEnumTests.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +@testable import Options +import XCTest + +internal final class MappedEnumTests: XCTestCase { + private static let text = "\"a\"" + internal func testDecoder() throws { + // swiftlint:disable:next force_unwrapping + let data = Self.text.data(using: .utf8)! + let decoder = JSONDecoder() + let actual: MappedEnum + do { + actual = try decoder.decode(MappedEnum.self, from: data) + } catch { + XCTAssertNil(error) + return + } + XCTAssertEqual(actual.value, .a) + } + + internal func testEncoder() throws { + let encoder = JSONEncoder() + let describedEnum: MappedEnum = .init(value: .a) + let data: Data + do { + data = try encoder.encode(describedEnum) + } catch { + XCTAssertNil(error) + return + } + + let dataText = String(bytes: data, encoding: .utf8) + + guard let text = dataText else { + XCTAssertNotNil(dataText) + return + } + + XCTAssertEqual(text, Self.text) + } +} diff --git a/Macros/Options/Tests/OptionsTests/MappedValueCollectionRepresentedTests.swift b/Macros/Options/Tests/OptionsTests/MappedValueCollectionRepresentedTests.swift new file mode 100644 index 0000000..98565ea --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/MappedValueCollectionRepresentedTests.swift @@ -0,0 +1,157 @@ +// +// MappedValueCollectionRepresentedTests.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +@testable import Options +import XCTest + +internal final class MappedValueCollectionRepresentedTests: XCTestCase { + internal func testRawValue() { + try XCTAssertEqual(MockCollectionEnum.rawValue(basedOn: "a"), 0) + try XCTAssertEqual(MockCollectionEnum.rawValue(basedOn: "b"), 1) + try XCTAssertEqual(MockCollectionEnum.rawValue(basedOn: "c"), 2) + try XCTAssertEqual(MockCollectionEnum.rawValue(basedOn: "d"), 3) + } + + internal func testString() { + try XCTAssertEqual(MockCollectionEnum.mappedValue(basedOn: 0), "a") + try XCTAssertEqual(MockCollectionEnum.mappedValue(basedOn: 1), "b") + try XCTAssertEqual(MockCollectionEnum.mappedValue(basedOn: 2), "c") + try XCTAssertEqual(MockCollectionEnum.mappedValue(basedOn: 3), "d") + } + + internal func testRawValueFailure() { + let caughtError: MappedValueRepresentableError? + do { + _ = try MockCollectionEnum.rawValue(basedOn: "e") + caughtError = nil + } catch let error as MappedValueRepresentableError { + caughtError = error + } catch { + XCTAssertNil(error) + caughtError = nil + } + + XCTAssertEqual(caughtError, .valueNotFound) + } + + internal func testStringFailure() { + let caughtError: MappedValueRepresentableError? + do { + _ = try MockCollectionEnum.mappedValue(basedOn: .max) + caughtError = nil + } catch let error as MappedValueRepresentableError { + caughtError = error + } catch { + XCTAssertNil(error) + caughtError = nil + } + + XCTAssertEqual(caughtError, .valueNotFound) + } + + internal func testCodingOptions() { + XCTAssertEqual(MockDictionaryEnum.codingOptions, .default) + } + + internal func testInvalidRaw() throws { + let rawValue = Int.random(in: 5 ... 1_000) + + let rawValueJSON = "\(rawValue)" + + let rawValueJSONData = rawValueJSON.data(using: .utf8)! + + let decodingError: DecodingError + do { + let value = try Self.decoder.decode(MockCollectionEnum.self, from: rawValueJSONData) + XCTAssertNil(value) + return + } catch let error as DecodingError { + decodingError = error + } + + XCTAssertNotNil(decodingError) + } + + internal func testCodable() throws { + let argumentSets = MockCollectionEnum.allCases.flatMap { + [($0, true), ($0, false)] + }.flatMap { + [($0.0, $0.1, true), ($0.0, $0.1, false)] + } + + for arguments in argumentSets { + try codableTest(value: arguments.0, allowMappedValue: arguments.1, encodeAsMappedValue: arguments.2) + } + } + + static let encoder = JSONEncoder() + static let decoder = JSONDecoder() + + private func codableTest(value: MockCollectionEnum, allowMappedValue: Bool, encodeAsMappedValue: Bool) throws { + let mappedValue = try value.mappedValue() + let rawValue = value.rawValue + + let mappedValueJSON = "\"\(mappedValue)\"" + let rawValueJSON = "\(rawValue)" + + let mappedValueJSONData = mappedValueJSON.data(using: .utf8)! + let rawValueJSONData = rawValueJSON.data(using: .utf8)! + + let oldOptions = MockCollectionEnum.codingOptions + MockCollectionEnum.codingOptions = .init([ + allowMappedValue ? CodingOptions.allowMappedValueDecoding : nil, + encodeAsMappedValue ? CodingOptions.encodeAsMappedValue : nil + ].compactMap { $0 }) + + defer { + MockCollectionEnum.codingOptions = oldOptions + } + + let mappedDecodeResult = Result { + try Self.decoder.decode(MockCollectionEnum.self, from: mappedValueJSONData) + } + + let actualRawValueDecoded = try Self.decoder.decode(MockCollectionEnum.self, from: rawValueJSONData) + + let actualEncodedJSON = try Self.encoder.encode(value) + + switch (allowMappedValue, mappedDecodeResult) { + case (true, let .success(actualMappedDecodedValue)): + XCTAssertEqual(actualMappedDecodedValue, value) + case (false, let .failure(error)): + XCTAssert(error is DecodingError) + default: + XCTFail("Unmatched situation \(allowMappedValue): \(mappedDecodeResult)") + } + + XCTAssertEqual(actualRawValueDecoded, value) + + XCTAssertEqual(actualEncodedJSON, encodeAsMappedValue ? mappedValueJSONData : rawValueJSONData) + } +} diff --git a/Macros/Options/Tests/OptionsTests/MappedValueDictionaryRepresentedTests.swift b/Macros/Options/Tests/OptionsTests/MappedValueDictionaryRepresentedTests.swift new file mode 100644 index 0000000..8aca268 --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/MappedValueDictionaryRepresentedTests.swift @@ -0,0 +1,77 @@ +// +// MappedValueDictionaryRepresentedTests.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +@testable import Options +import XCTest + +internal final class MappedValueDictionaryRepresentedTests: XCTestCase { + internal func testRawValue() { + try XCTAssertEqual(MockDictionaryEnum.rawValue(basedOn: "a"), 2) + try XCTAssertEqual(MockDictionaryEnum.rawValue(basedOn: "b"), 5) + try XCTAssertEqual(MockDictionaryEnum.rawValue(basedOn: "c"), 6) + try XCTAssertEqual(MockDictionaryEnum.rawValue(basedOn: "d"), 12) + } + + internal func testString() { + try XCTAssertEqual(MockDictionaryEnum.mappedValue(basedOn: 2), "a") + try XCTAssertEqual(MockDictionaryEnum.mappedValue(basedOn: 5), "b") + try XCTAssertEqual(MockDictionaryEnum.mappedValue(basedOn: 6), "c") + try XCTAssertEqual(MockDictionaryEnum.mappedValue(basedOn: 12), "d") + } + + internal func testRawValueFailure() { + let caughtError: MappedValueRepresentableError? + do { + _ = try MockDictionaryEnum.rawValue(basedOn: "e") + caughtError = nil + } catch let error as MappedValueRepresentableError { + caughtError = error + } catch { + XCTAssertNil(error) + caughtError = nil + } + + XCTAssertEqual(caughtError, .valueNotFound) + } + + internal func testStringFailure() { + let caughtError: MappedValueRepresentableError? + do { + _ = try MockDictionaryEnum.mappedValue(basedOn: 0) + caughtError = nil + } catch let error as MappedValueRepresentableError { + caughtError = error + } catch { + XCTAssertNil(error) + caughtError = nil + } + + XCTAssertEqual(caughtError, .valueNotFound) + } +} diff --git a/Macros/Options/Tests/OptionsTests/MappedValueRepresentableTests.swift b/Macros/Options/Tests/OptionsTests/MappedValueRepresentableTests.swift new file mode 100644 index 0000000..e400539 --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/MappedValueRepresentableTests.swift @@ -0,0 +1,40 @@ +// +// MappedValueRepresentableTests.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +@testable import Options +import XCTest + +internal final class MappedValueRepresentableTests: XCTestCase { + internal func testStringValue() { + try XCTAssertEqual(MockCollectionEnum.a.mappedValue(), "a") + try XCTAssertEqual(MockCollectionEnum.b.mappedValue(), "b") + try XCTAssertEqual(MockCollectionEnum.c.mappedValue(), "c") + try XCTAssertEqual(MockCollectionEnum.d.mappedValue(), "d") + } +} diff --git a/Macros/Options/Tests/OptionsTests/Mocks/MockCollectionEnum.swift b/Macros/Options/Tests/OptionsTests/Mocks/MockCollectionEnum.swift new file mode 100644 index 0000000..6dc0e00 --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/Mocks/MockCollectionEnum.swift @@ -0,0 +1,61 @@ +// +// MockCollectionEnum.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Options + +#if swift(>=5.10) + // swiftlint:disable identifier_name + @Options + internal enum MockCollectionEnum: Int, Sendable, Codable { + case a + case b + case c + case d + + nonisolated(unsafe) static var codingOptions: CodingOptions = .default + } +#else + // swiftlint:disable identifier_name + internal enum MockCollectionEnum: Int, MappedValueCollectionRepresented, Codable { + case a + case b + case c + case d + internal typealias MappedType = String + internal static let mappedValues = [ + "a", + "b", + "c", + "d" + ] + static var codingOptions: CodingOptions = .default + } + + typealias MockCollectionEnumSet = EnumSet +#endif diff --git a/Macros/Options/Tests/OptionsTests/Mocks/MockDictionaryEnum.swift b/Macros/Options/Tests/OptionsTests/Mocks/MockDictionaryEnum.swift new file mode 100644 index 0000000..0cb80da --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/Mocks/MockDictionaryEnum.swift @@ -0,0 +1,58 @@ +// +// MockDictionaryEnum.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Options + +#if swift(>=5.10) + // swiftlint:disable identifier_name + @Options + internal enum MockDictionaryEnum: Int, Sendable { + case a = 2 + case b = 5 + case c = 6 + case d = 12 + } +#else + // swiftlint:disable identifier_name + internal enum MockDictionaryEnum: Int, MappedValueDictionaryRepresented, Codable { + case a = 2 + case b = 5 + case c = 6 + case d = 12 + internal typealias MappedType = String + internal static var mappedValues = [ + 2: "a", + 5: "b", + 6: "c", + 12: "d" + ] + } + + typealias MockDictionaryEnumSet = EnumSet +#endif diff --git a/Macros/Options/Tests/OptionsTests/Mocks/MockError.swift b/Macros/Options/Tests/OptionsTests/Mocks/MockError.swift new file mode 100644 index 0000000..9915aeb --- /dev/null +++ b/Macros/Options/Tests/OptionsTests/Mocks/MockError.swift @@ -0,0 +1,34 @@ +// +// MockError.swift +// SimulatorServices +// +// Created by Leo Dion. +// Copyright © 2024 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +internal struct MockError: Error { + internal let value: T +} diff --git a/Macros/Options/codecov.yml b/Macros/Options/codecov.yml new file mode 100644 index 0000000..951b97b --- /dev/null +++ b/Macros/Options/codecov.yml @@ -0,0 +1,2 @@ +ignore: + - "Tests" diff --git a/Macros/Options/logo.png b/Macros/Options/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..02c0f98c823e47bcc7b047da909f16217a917f74 GIT binary patch literal 89318 zcmeFZWmsInvM7qXOVHpFAUF(e0RjXG3GNWw26uu>fZ&$klHl%xy99TKfx!oN=T7$C z=bU}dJ@@^3zuxy2-_EfA!Nmc9)gi?p{R0OPtXz`=|6l#*Ap8eD1W*p*f0PlcVC~>|xOljQxp;+nxoLQ~ zgn0yo`S{_Y14MgZRp^fLIxcWtktz$wUw2GO&#nxOw1g;DVb-q{$Ij#S#Gfxx8e**o382=oj=-&|t z>wGqMajQ9xm9$$^G|J^dAHK->Uy>djAB~{(lDj_v-%+`d^S5KxtGW1J0bu9iW#{Eqhe-k-uP{HCt|;gK(d@sW zkajkQ0skKe{v|>GLhx^m{wHt;XLSb$JMsTXn*TX~f588%)xQvka{lGzf8*_c3eG>? z!X!r=0|xmYQYenG$krtZ2PX-qAS0#j34iz%HGr}&+1>4Ct4@cYo6giU0h^L3!phD$ z1&M$uttS8-FhKTj$ZI*>zmqL+h&b+-cgt;ObyjE8E6MtHYZyhe;_|BE7b;=x!{&wY^f_a9mxANJK`# z1|Ny#4VwHr`BSt!8k@8V`d_8;a*-9bH3h{A25P8$8qiN>ck~8BZ8PUmCdFL-?MoqC z?^4NRjH@0FG!4{oF3_@qT@{vkf_qgAh?7-6+;k~#Exh>tu)LLn1k~E0j zBMdvT%ZHf?2mG={{~I9j7H7I$_10S>Rr z0g^a0s+jO#Z}t$d&x)7Wcc;uO{+;TpF zycl*>df*N;pS%pBi{&VL(81|@>^8ltbf<@-T#pW&)motdMPwU#We5;Gkr=)4WdPXF zYa(h^`Wj4E+sCaYC^EiGocFAcmuun7*is>(_zPM(un;|_NRSFoQ((Q0T(xO^du_-C-#(QU=yvnlF%{pi5mf%LK;S3QopOYovFcSkMYHEYU{Rfl1R#M>}A!q zOpg*Oo$X{7Q1oIim{ZsPao{0i3USFCH;{dmcUiA(Qjfclvx^gmYKkp;T~}5X&pP}B zay`HE1w5t49HSbQ>Jwz~i6C@dSy%=K?OEj% z+fY#;b6QRX&%3%w)MUn}$8}R6AWDGF%Z%SRmr4)_Y2anL)aFJ|7%n~$xjY00p+4!& zXLfv?O2V$Wm4#~>J6QBobMq39Wk`8+}a^1e|r0xbCX)699}KkHLeAre_GbuO>e z{*1kdxUH|ImN;$Z6_zY@r^^}7U}40GUBmnK-r)jS8g*&0A=BPEGGUALoPc253Zt?8z(2!?JqC%G~f@7kc0HvMR*s)>o2NR%eGx9vEjq7Y_fiBT`W%r zi)l5kU4dOjr=dIh#cQia3Z4zV5;IfIY|pHdvv0+iC&^ElMl5;uFOLjXam(ye`~+Mi z0->F5jTh8{V}OC5yv{?*syllzpid(r9h%sk6pr8%#!x zW^80f>vdEAf@fphB7J_xe38rll|7<5T@i5k}8=KTMiQYoq`uJw1%K(jw;S zaVd9$AxdPR1-M)5rZ%X`VG6i5Ce2r2&S}Q)vDl-Jx3XLmvN>P~-B9$IX!zD?e50`& zzP#jjgpG8=w!{Cxc_#M}=kn>KmTkS&W$tmd*kYiE{Ry?=Bc%fPUPj4t3_j)~rI@DB zSV+9c#MkXhZOi#Dlq2n?bgpsIc-pnz^$lWK+UNDCDTZj@PJ?0S%^#5R779hlMbP(? zaA`MC!%EWH8=W!A8y(AMD_cl=UKRMqb^ zfHj<(t?%^ymu;-9F&rs94oj$(%O?k(Xd_f4b=9QQvyx+$ep_jU7QDTuNr84esFhIw zWQEE`E4{T*ZL6UGdZ*stcyf1<^7QRSoIm)v)9oT3OJ5-NXCi+9WM|Sc0un?26eVTRhA|+bIt`%8Y9*3dB z{SF%?o|%GBILAz!gibeML0wv8K^0UDO+n!B2jIc({1ea0nipyl^91d9WHQ^NDnLT& zhZfO;8nVd=@AIXdcenIl6;j~s3Y(?OGV?m8x2TCCxfM@ta#QpwiQzFCQ^&Q(O&gm4 z8N-MxNt24ln*gZm*)LjbK^4TlRUU0{(>5Du;l&+2=IcYOG5DD3_I+i6@-ZvhySciU z94)9nIM1|0y8+JZvn-9%jlhZBe%d`3Y15@~d9QtkoG?g&Q0HlHg#J%rb`}OrF&0b> z^5pRSK-PD_ll(Iq2uXtP+l2M;`#tb^zOf9Wp)OOAx_KvMLEIYS-0KfDO1MYi!;Nih z`^#lU;usK^RCe_Be0TnZV`=uvh4P@=)LwCvv5ma($#6XIb#4Q0%82-J&d$5O#WjTa z@~)1rQ(KW2f*al#thw+etcP`(5J3>5<~C9 z_!ir)WDPX9`SN$K{Fi$R=d{uX&I-POo83-hKcK|KzLR$}pEQuxl^~oB_cClg9`kwn|0@0d5QDJyAmdS-LSN+W0B&NKxy+cV(otX|bG_+H%(8Z!wojch} z40DEO5GzvQ`?}wPn?u2xc-WMcaNlJYRh%=@;?p0l%1?Zr;2l3zePh_}ZSZhS8qSI< z+|+K)+yDoKbKL)NBBXlvUKuIj<^1LbS#P;hHkax1B?jp>;CeDzR=VqV?3kzxr+2wP zB?Gwm$rM+=k;Dbu)aIEum$4;COrIKpei7aszJzPw(n$KPS9Rfp9|>XYJCllSY+LJI z9%LY!$)w2r;uW2V`6*K^G>rt_(i<4Iyf9(!fZc2ObtkfiR?`Ww2gb;7ttcf3^AvF7 zW*Xooh0Zs`9tjZazvhaO2WJR+es73yuWKJ&nC%9!!O5?fQ{f)sv{vIsX07q>uC8m? zpNKMOgUEmnqML>YHa@dt%6AULO~;3%F#a8&76gj*&+0lxLa@m|5g@HhYWtJcHr)a6 z&w8}F#)dQ-$xrozQ?~6GVL6`?m!+v!oTcpo<3%(F2E2$5#}X#O@OC_$X?ow7r;z-8pOYf%FXAc~i5|9PGjMJ9i6&Y&$uz&ZEbq1DsKtD+NVnro5}wXrx*Q z@vS1r*L?vEfa~!q6haX0zz+X~Ti(M#up>jLPZ}BG+`S=ZqgX=I4Z(O!xHc4*?Y=1p zTGEY?p?(RInLsD?Z)}3%OB5dZf?ZD2?}5-Qu}<7n?)K2U$!7j;OU09it&Dva=qqqu zWV^Nv>L&4f?f+~e=K5as(@r7_YOwi&|G%eqP5ka zy*FG%5UeE4_UUWSZHPH>TEm_%Sx0MR{FG6{OMD+}+r_=eJ@2?mBKd}x`YyJK z{SD7M2Z`{BKUzw3-I{0eInQ2{P2xN$6&r$jGrtO=S1&*&^a4wZccdYh`GBz*5#DRD_dgotL$E1k4AElF{0`4F!)|ENcCjD z2!DxRkH)Y|i0WM_<;0TFRk2Grc3vEP4~iB!ig=IkGHkxf!g?fJA$KYzSdHPIvgYO2 z8y!gJ=l(6P`^xdcdDV@wG1wK*C>07}+PO%3&w<`U2s~-(v7pQmN<_Q;dgZ^v3iu86 zzO78nzFhC~X?)py#(36-R<5pnTzilUUY4rdRgB`y^kY2Ho+<6H1wC)8u}V+XBIo|b zbOb|{wt2pboqhT-5Zu1A)od#?Mk+_4F>rj>S`eQu)@;g6c|WmNrE8Skza?MSdnQ|1 zYp4g%?KFDR9*+BUAspLYGU@}GD#X3h0qZnes*tcQj@YuS!uK7e!O@^(i(|bh{COqeD-03c<77_du8KwyQP3? zW>g9KdWwIy-%etaYQs?Suc0IDg>_d>fO6LrWUTn9k|Di6eTqu0F?c-C_qIYW&^)+v7 z{aSZa`)CETGSElX={#YP`O&o2cu8IVWlEtxEV*~~>j|T&xjhH6z5uSLn$wD?=*TRL zuZW{p?1~^#c6=JXW0cN0cnNRFKu8~2KMm9aStELS1RxqKDmhpZXcOBFC(DnQt=!7# zk#B^q>``Ze2psTC?lOoMtT4El7L{m)lO*7gqGZ? z6N>^q^W)RVT}-JM#=6qj|5O|#>MUDs~Wbfl=<$y)xQc{qns0jcJOWQ(}J z@vwitH#>kgRaXsaFhHD-mcphK2qTR8C)Rlq4C)@bH#utdNP~aaj(!!T)miPFN&I4; zNB8=%Od>MLQMV|Fpy{Yb&^IQ>Av%}*NhSdL!-ZigNT)HBPGcJ(rk#tLmLRli2T5N5 zMbL4DROM|-O(F#HedVu)CSYV4{3mvG%VdjcwblJBTjuIx4w(( zxA-kVHB1a?#&@koZ4tACRh--BUit89sp);Y@tzXocP@h>S`jj|DH^xcTF-Y8ow;Ua z{k}e4+T_{TZ%0my9 zS;?CW;g9p*WU6*-nuln%>E_1w*9JoCxshV#`@d}yxV!ky3}T~vanV6RaV?Dr_^#Db zrsNk}SDAcXo^-@nREzZKQhO0)umK0Y6a+K03?MZy6TeeB7B{!8Lwh54=&=2W{upzs zm+w!p@tNo`3T(_QiDMQ{?&G`p?>W|r<@Yt_EqZf6CP>ag!{f#`oGsTOZ(<#N9=mEi zXDD2$q&jVYsI61tA6K1I*i<}`DzxsjYF{=4g=^G*2SmvAel^)gI5@`iirRG&aC|KY z3@XHWRS%;)zq6Pj^-X#dDdopy^*=g?6*(KPJEVoGmm6?C*$qN)DWyJ9eybsajXF9w z!SlR@fMj8XT`>)@Vm{zX{*SFt@7IkdbAEFEXVNA^3O2B({da8+6M=#7X#LIDD2d(8 z6QMXyS(^05Ip$O_!Kv5y1~&C($2K<7^^UT`goglvyW=u_gyjh^ew+>59Ox9)uyG4Y z#3thV^vh#;a08#{ogl(|DFlbIG6om-$C>nZF`=^>kxklUMKRPc6yUD%zo&)$zKu4rl!9HUt!af*APO(T;CX>9W-n`DM zh#%ia;bUTDgU4-Kgv9N(yb-0eLMJv{_Mr2+0~9n0If zpw(dqngB`4b^!oq2}`}gw>D@^K!kXu#!ae;s=9T5}1vX%`i~r71f0 z*52#zKuz~f$|A4e?@-l8en!4*-31d<3tSpMJ^a2H+H!$WGUNDGB;Yxh|HC zO92uT=WtgK>SaSHHk*1i8!`No!LuncmCf51bqN87?+ZGDyAuT)=Qo{g+Z5Msrrb`q zL`l7k232)hVrnNN8Xy)5p<^3BwexI=v|7I#JtmeEl(%P2MmkY0j3B+QbcH~a{UO0q zRMsga>iqr@kH6PBsob_x1xWu(?-F}i*th=!N=2+}Pp2DNcF>%P7va)^#ZXCSX)Ntb zhp8Q~&-Sm=`JNhXKrR=24nrUHw3-S@%s~oN?3LU%LE79evzPxC)Kq96&A*^p^AM>J z#GrGjTqCue(@cwWxCO{U!R7iz6dW1=b;J3S`mv%mFT#e+sLP~3Wxfn1Q#kmJt-|7> zqHaNuym@H2PFWjA%lO8e<0~oBfbw+1bZSI z3l6zQLh{~t2@7_i&AgS8oadj(u5p+qvo@Tr+Zc^xEUEHhlTTbw$Eqs{g+q_96lgqK zLjtycR_erU5{D;HBdd0Qj5IZkqutDJIiEEl&ipX|f)Qec=(i5*;g+w8rt{e=HF;6G zxWg0anv%tm=9rHmRrOsc6i|2>W%px!U8RHOn27)u_suaa9PKi#%0BMbdX99}_&os+q4WGZ*4x_} z&8eX~eHnz!{(*%0K$p+d=Mkj>@eKyZly~^$dqw}I0FGdJf&1km zg|J=OT4dQ-wazD^&cW9rjv4wQL-xvNAwq%Ht!bTCXP$h{0!J5uzkY~O2LgU4JEi?8 zrfn^GIBOCu1vWuoRAFV+W}V-MQDw^qouLBnjoEY&r};XI;!a)=O7Ealag4MVwW z;pXZI%P}{{wBv07jDvp>l}bLP$zqdYI1zp#ToF$^28lGwIgOufo%oo@4iD>3dw zl{(LTg|%lJnq55K00;eWjaSM>h9)QYK}n~`6>131Wj|=d;bP17bmJP#k|wb&>w9rIasp)dS>+ zIH6(g`2E0fhzo&XZ(;zh93Id%4DA zVBk&|9~Df8RQ3_LXVvm$o6>6`O9#9Ls?Wk!P|YMKPowW|&{jy{J?T!$G2V!pp#-iS zjk!=zP>&t$*f}x;K(P_Di-jX2Td-_I>ptVzUVw^<4wyCFNzJCEjCbeQ-!P{? z^vV`)pM7?e1Ofpr){(7Ft=EnNbO>dRdei*C4jcG+c8hC6)KAs{b^!X^9&+Wa5I%OJ zmlVXqg2BI}j;`s?x-T2urTdJbc(gBE_n8yn1MPS(E61eKv@6iJNki&3$8aP!OAM{5 z*Ir|`X+c#7Xchq7R?Yq4(V0sAN^`>X(y1m;V}$_wvz~al$azr7#a|vlhbL_{cM>NF zN8uUg{zhEHhY~oN4xs(nz5GHN?`HHTtv@>3wxxknTo~=$)~wh9K;0~2IkLpQCU-c6 z4_?0!Y3}S@hvUqxPohU}XEF=*DHo-eN$K4nrl>Q_8cT4*A+m&FFMRSAU$cV`3qbVc znlZDm!n1$v2;ex@mc^{;kM@b0SS>Gd?pkytGVKb6I-ynd+sn>NP!`h233R$qpxBNh z;&o4&A1I*f@Dhj>GL;M`zQs$H$paJFFb; z?OXhQJ-&5;o4Ql&Te;K4nc8mjz zHxW8dqg+9W6mAJqz0q8qYdmG+yYy_JyTjn?ZiI3T>44S<|0X}g&u2jWl!TIlmC($t zcFXbF5R+PHH*2H0MqfJ7ol2)$dVgg-CaqD9g((Bm@jA+dd|!uq;Y>ljyaMwuV3-%i zrsm-@)k;)57qC6A>v4ZyN)bQJm;MdX@1yglJJ`@4_epw`ff;W*v|4wz8zBS!`sG8; z86;mP>4nX5vbgfm&?411AcFHUVGGm!cfH{yYP2BOWTR@_^=EZ#o zrD8dh54c;kZ%(0TDzS1?m5#t>E!exzkMBVF*GD-Pt@TVBmy2HUWqqR9&9ybeK8+8x zx+;YJ5W38DWl&d!0M^P%&WW$fhnO~<0zwUL#s`2P8`IVBr7IfAm0XF(ThpWw zjWv9|Sp77&&q98&{=kQ`V79YdJi^RrD+HvPKXj6t%r#^7hqlkDHGf=wpzAk!P4wUH z5L9$TX*ni(GN$&)Jhv)Jw?TDgM!&0cI`LXfvJXT4x}OAZlHQq67|2Ve;UmrYpQ9fr zT6`yR`-LU6#r$&)=<>_yL-Z@2{p}=~KvF`qvKKS<>6N+o3eStp6J^(kyF8evhkv`> z@qX&TZkJ%l&k}8c$^_Bml^s4YQ%qKuv4ES*Cp3viU|o$3j{Z)-)i|OR{T0(WhYkHH z+yL`PkQshiO0@g>fGk_Lwt2155-l%`&pMAX%KSXLAj880x;12+x})&(*0k2DW4QzQ z^@0iA1z5`_y=~9N2b-2!pv|aPjw>_*EUzGL;?$N~@7F2r@k0pm2P4Vz-0jxB%^e+- ze)@Aa@U!)?`9hbkKniMrD~giaOWre~WN!#_Yy=Ff3XDXPkSmr&K8T!ZHPu_YYdOkI zo_ZS)@=^+l3zszLpNeM3@;Zm!U1$iw4stPVl-C9;%F`#8jt)E26Z3ruLuUlMs5w?} z#j=$<27M$vC$dRk?#FOV){6iY7k@sz<0_VJbTYfM7?-t;Y0%pWWqsl})-^LH-i8R& zm}L}xR_B%WS5W)n$G=2k%yTJ5lF=z5F%7;N)SHyk^B{kF-p6Xi9io3b5Bg~PB{OrS(0$r2Gs77AvyHd<{cazOHddbxffo)~r~|fy9j~Y~9it=}Yd{jjm0mCQZO~Xw zu;)a&=Lu@*{YC$gE5{3U*_Xv4*mli({4&E1%K4|G#8NHi(_&U+zg^>t6h3T9*uwHD zcUw^WKCUb3!^IsEed=D;M`qAXmzh15{EsR(TZx@+)W&bGh2S<@9kIg^FZrc5DK~yqc`s;< zS}p@eu2P1*7-5?G@cM;OW$|7avW>`-)b|ty3=8onl!YR%fEnY%6Z+;UDc7mB^^ z`HZQ-GY>X#?NQgV31@ox&1l`=;31bkVh|w*-J8ciCFeb-tcT9X<5p+A>8lk<4mV~t zLEYb|j+s<7??F@OW5{6yUhGkgZ#C|e8Z^jW(>CF@2?{kwG#c=uZ6zdsg($c+=#kRg!lSf zr}eRI9_CnQGId_{SMv|MedL<*%uizQ4Bo&d5xwD_=N_|_f~TwuRXy6Z5Hi%u`^soD zx(nMNo@=4Whvy}cXa1-fKe*=}wU zRj)eg-w9R=qr`gv6A8zhL%UzQxn>Ttc3$0wN4KKR^Twjy7@P8^hG459uM=Oq#wU=GA3loty>v9x6sCbnsqiF?4t!5h(73h?PK&)D6=@+o-MBC(Eir zGK1))-RHX}yDxiW&7TceM;TZ89Wq1BG}|YC=c`xibzVhIDEUf8K)Z%~RFdpXadi5U z8OLP-fPE{qPA9@swauo8SLG}=j(CW6 z{3Kvdvlm_9`7mzAv))$QKK~d^DUmyE7(k6vzUbYf9qFwUn zJv-|LrkuFY%~0%Gy}W4Rmq18;cqr3=ZKH)fdj5r%GJWdpjzt3cd}u-*e24B}K6ZAQ ztb_k8I{BvORl_&rh@y#9D&bc|^mcXCg-7|jXB_f{*Y>BHNJz3?-F3vzJAIzKKdDbkgn0=M zDuYmb-@u%B)(Q^kjQSz3vC?^a8AR)w5dG1iKcyt1=l2~g-lrdgJyfyU=(e2&WFHMB z94X`m+*uk?c|k^_KVIh47<<;$8;!p0!?u0tRRAeROU=k%19s1(Fn63LA+n*l@aM5M zN~Lo~-t^TSS$FfX`X1ds@wbe{sbdL7cG1XqoOdf%xn0kse6p%a{T*NIoY7>1{I<^S z2J#n?JZ`T@uk6<&HT|2Zj=nR;M}E~?NnntAn{hora^s=s|NR=mNqsbuS^HvUQJwmr+%Ap zHPXzPvLi4o=ICqoOHt^UNw4qFH>Qz{?Bj5Sh**A+cU;JiG$PD=Yc-~PN4;<-_>7bp zb>yq#g&4riWxkTsP8~_|EY+G_%Gj#&Wb1ZEx&EKkk6CS-Tm0g&yHTC?9?`r2qnW_m zL+jMH-bch9S7py@aPvo*1BBUrsxQVrixdFq5%JfyV_r5_PfR7Cnm3LshB3>sdEPrN zv1Hrco5c>Uz1^5Yi~TKOpL<^FLmP6f6I)cFzlOd&(z~c7)RNV??BdkbOT?Tm2d6g! zDmWtxDjh5kQv)VbhYSFW++yOhr##`G~O1R-8~-xPQpq1dhJfV;FdFX2nX$-TFlA@fPKCNyh~_qmSsXvdFy ze>q`s+MgKv)`629N(F@eSZZw45nYaO0m65Noxev+n6E$TeweI_ zoUG83hUY`4Xnp-U6D^#FJ1@M}yoxq`??ko@F}R31-ubHJNIPd})6AdsE2J;B{Y=92 zBK_|EC!31l{*5P2WeB`u3jvSawke|Fv4WXOTb)Ap#%!>-V;j}XL22Sz4OOw1?cv9B zWQ}hP22RI`wltrWhECxI6yY{58{+R)l3L#3XLs2h*Uja;U{k8qm&H?#Z{gkH+Mh^G z2H?8&(-pPVV~3vk2MvZPB8qPz^gTSBcA+ZR?U|?bSFy*?-i@;T(K80e$Rg#Im1RS( z_H0kHqiY;2w?V6spw%&^#>5}X9PVIwdCIoINUW)A7)$(8YIQDk)%F@P+*tdIM6vnpPnS)9xu0`qZN4$L7jDa}8VWiUv@EStu5T zxqL4Whv2U7C4Sbl#yX6&f?WK)R=-r+86yKCTAbRbJL8nrxc=!qB1)uyTfAkZ=(d|( zk!}MW+Dd^UrznY;Pr^_lr{3lDvMXbYQJTH}z;nLrT5RUPkkcN9d#Td{p9)*X4~7rT zR1u?{ayJ~#5+eJT6M&fD@^|K)R-?OacUv(>T@AT`Z8zTGBqF2S& zS>)1+{wZ5=(H3WR*Nw(ta*Aa8^vPni!eZM;Dr+NC{*hz^V0usKduwy9#5NqP74kP4 zo^}-TpIpWvS&mpN`!b=QxKhMgC*Kl0+zG+p5f5uWH#kw+5vxHy=W^BGwQd*~*Y0$P z)Ujs?kI_eriuq`evZU11B5#8(s15zt6osqHhWQm!cieGyKKAxoNep`j0p+RX&36oW zUarF7qV8c4#q;6mi@IGE#TKPWNhER1OXmxVAN?+S5>OrW5aGd|*Z~V(N^ar~3xkYJ z`VD*09gMt-!=icM>q_OriOye4H6`u-JHed(t7i2DoPM)}l@7yO7)E{6MC5vY*4_-| zh&1s-s~%^M^Zqsln4`30O~5BXOhKILJ-J7_d?;dU)cz+v%^46DnlYj}ryMBaXS z$m6Oi$Ib4=F1v$OaLz@Wu^b|}`N|Z3FXOWo{j=3!FmJZ5$OcV8a|pi^BUrE{*rCr? zWpt3SD)VKq=AkP0;iG3TDQWZfQ#1;T^!EEsMO2CNxN+5JDrj%J7faEdz{waQe*;4ds$V3CPOS%UZrHw6Zt|wKx z<5KdTLkiOEHT-POmEM7Ul7lQg5AaTM_*Mqaa({_>Nb<)3S>XQwfk!PN#UqR4Q)(8_ zcV5kCSRH2)HHQSvpQUvF1_I)v+xoTPLumhejbA{u6nz@nEuZ}5^&4Sek<5o}*X7_n zN8r(8xY1Lr48S9q1duP(Pq!J2$<}naG0>jPiEH6pxIuhQdp{+W2an`>SbHU+-NhfE z9xVHh4aVQzIkvH^AERQCwxSwZ-FBv{g7joUt~nhu0C@%5I^x-SU$zo}Sr-#E686xK z87z?qtMrCSrVIMS@?eO*loyq+V>!i*;!fN3b&T2lUQmgBV+C=Xek9y8-!H6!S_ydS zmCt5nEvOZG!R$g?@|X8)7|bT!Re>#}zK(3~WRBn+Gsu$)kQVu~1$;?m$_?4u5BIDM z;^$&d1Mzcp%{RPE(c+Z-8E`m4&~35g^6RNHz0?(LX_~RJmpqClg;guWk>rgX2~bJ8 zLuSK`^6LYj(R6~_>xuwXH-r!j=UU0)z5UeUV%78=?{ z@OmZSBTG7$q8{Q6F(l&$zKrn2{PE*BGCxjod-Y6da=#53a>Lbo!H{4N}_5oBD zP-fjy6*YJV6T;_|;pTn~j{xXpcIxEh+Qvi=O{=R4ug;PWJeIm(7Q%Zn6QtN_K**sE@hVKTFU; zOX=cR1|5bKu3+Y5yQoe*jc6SuhdYneMTvGF{%$wwon}}B zpYa=hP{35Wgsfmt_b`nA&sea(1(hV>2i#>a<&2H)Hc)_&8Z0Yry%%6B2|?VcP#PC` zGGk%b>9Pxfb>w%1*NGrL_iEbTm%n%#O$zT`c$OUASc)N>==&#mShDg-Y+hu=4(g#X zOrwDZX+-XMekxjWdO|g(lXHXY(TG4)R}W)7>pO3kd+qeXDXoeEKv~p>ZID*RQflWM zFRL091lgD#Uqi$q*4WIf@z+oEkG+S4{;T8|Ds zhu_)^LdmzOMvgAXuoIzmDR<3$^F((rG7i!B24h`k&P9 z9`nk0ZliTBv`7R$wd~I#RiqcfIj)LYsK8<<(&e&=V?#+V>R>%&ff+?`@-~s3Q+A?k0U+ah@KOuVjy`IBn!tK849XNfw@=iMkEz__aw~ zS+=qqy?c})e<3>Vr&Co;8kJsr)Zis)t#-8&*S`pa^?54@KOb${_gMklbT(-Wi{_^Q z$u7Jy@?L3N>e(=YC|h@Z$(rpLx}x3)UEwzIb+YST@H6W5+4>o1PKrQ4{+51tc>HmC zm{~U(eXuaLvo$JKESGVsgA;s3sbnO)PT=(Br#fBg%Tee>%1gjWR=_n9Of{Lqf^^tS zd!`A&p4*dO;vsfAE~G7%?M~;}j!0pPo~CKrY(}v2h^>2E=I`282jWFp7k$iVHeA6A zOAEDM6di=U&dcr`?5$KO)jdc9JM`VVu_psMC_3tt+_i}Z(g%#}x6D-hSbxq`f*yy= zgJal`FjQe#H|-QE;CtZP6<1`~xq8}Lmkc5LMzrPW)a*w}fcwXu=faeG=${Cwq@zVm zJNL`^`KcHL12wsmqgI-Sgtz@ii~r^!quDZT5y z;qW^w_iI@Wzg~EkGwAm6&0p9tvwQ>I{tb=l7R;$3>ik6mJ6>vBm>=K}dxn;Gf&K49 zH`^B+QV$q(ynDY?E1y%W?qbTHdJb6dyDC50JAGi{y$c`zYPQ%&PJohZ5ZIZg*m3UF zv3G)V*Jin?@dPjw`3;%x%P6ZD+`4%28hR8s-mRz3X>^0p;6WTBeEn%R4XQJ8_11A! zxWPg^~;Q-5g(<1K>b}}wet5C9F=>@^M2id z?Vli8jL5tnUH*^j$HNwt$k{Tyd;D69Ua6EW=+_Dz99tK!!@Z`vy-y-4?F}{OzNCf> zpb*@@fR2C8qiWBSU78}oQ-QL2^v4nA7isWNbx#MK8b@}qDZTFoox%w|-k#24AuZS{u$~P~jPtbu1UIiP;pNHvV)u#(@u^cd>cZu9I8fYZqlWJdX{%&*iS)O8| z%>=_i^~Z`4;I_%@t3YcbCRBuI}x$v9b|PLHqZSbvVbEPoGmcuU3(M-m_zj21^< zJ$-kHmCcZ`aV9V4DQnFt&cHC2v#>PlrvApt#zAUw?v?u8Y(}1_u;s>bsjXHBL4f2} zG{HVMY!?Igig^Jm)nOt86(>smN#ElS^o^9mhOGx7(io8;Jpcu{s64Jdwg~P+%vYV5 z?FnH9udCoi$Iw*l^`rRAABXa8)d37&dL6|Wyjq+6PY@rfWtX!#i=Z_%JTD1%m8(V- z_JfE>WinvS+Ss3Ewrjjx0h~1JdqbwgRJcV{t~MXi;Amk*t)u2ar?8On$Ck}P;^xf#*#}+B z>OIn0%YD*ZxiuqG)CX;~x~d{tq4E#bTP(kl1NXpxt@AW|lD*mom?_@kpp+{I!H0{9 z9Y8#WgO`NEgJt0V|BwH#lVF5~<_F7RO3nW}iO>hH>~g4m>A4oZx|MRUhI=86OEohb zZAg77q`8$hYXQHI0#tgiH*1aqC(UiJ*aFK1PsmGIb zCJox{Ivj&!fEX<4@h}?QN`?gH4?;Yfmj;zx$B&6xyY$2YJ6WhIU*PO!8cZOwvC-Pi zPyKU&C4(%o9Cp(fcOBcXBh5y)^^Ur;4S4hbNiU?!W2m%Kl7zvz!hizR`UX|@i{!{j zal!y0hf$AjMTK=F({Ni&#(ECX7JrGpCkb)Qc>S~8n()O`4hoGbH7tGY-Z5DBkp`BI z0xa7j_nF(bmOroh1dScJ3Vmm3obS$RnAwL?&Z{t>*s&lnXdmDa)dij7o|A7iQy^~(*0Uz?BM+}9Vmm^TQ~ z%>?l0s1pAzd)hGdRB%!U+)P;1(xD7)`f57T7N35*pFH3tJ?VcI+Aa4bAMl0Rbw_uK z|Mht4B0EU^9G6|<@k!sMKG&6(F0Ot1l3p~;H?}ZN$WW=zRGtk&>~f&=X!6dLi0XIT za>}?_3Q5gRiSFTyeCaNGNU%gkZ6gte-!L^+=00{9P9KMv;VThDeM=|x+X-~R;}Jn8 z>#hEl-NW73y0u+Qn6VpXKS;KB;E-H){s*+uZ};Vtq+H?|^7TqFC=Do0<1#&8sPOK% zan1LhkCr%=X7iOH+t+QZ5W4dE4~yse$(8znH2?9x0Jfj?h3|aD)1Q^)Zh|Wpr{3^& zGa~3UTQ)R$=QnP8JrcCaJ8>O{)H>KQeS+D%NM-0zhy$6_t`)FEj@9``E7vIlAv zCn{lKa;uWGd9Ajk^sBJ3Z_fjmwtMo(EUmP0pzRsGC+BM%Zf-8@;z+Nn8wsr3wusD5 zm2S3{>@UGL|CwrClTT)~$?$(9WwYc*z&mC#r9BQK#MJVJ{rA-C5MpCg;m9<+{GIJk z`Pe!O=Zyx3Fu#j#dZORKZ{FiiR7(6wzma{OPF3)emLCYlE>+NU87kp0RZvTE1#s6% zs{B5-X?e(1{$7lFun-U+?oyB>DC#XuL*6z@g7w-;Ixz+oJK}-l&P0wJ!^@3Dm}ERR zxO%?&v+KGzGdA=Kd!cEeH09jzHp^P@#JVB*@h_^#H=**o<$*7rXB`G>(1OD(zhRx{ zpseRw0U^)aIK}DhhHrhDJi!Y33Uw&0=odeggunV|-5}cjR3}KviwyYRQn?Z4Wik8>sv~IIG{FgO!QI^*4(`E1aCdk2;O-XO9S-gm+#$HThJ(Aa=lx`B z_y1IN*Yr%!^wals_2RF6+nM7@y!Hb-S{K)me#7cR-7f(Xg_F`PLw--+#00owPRqj! zLw(zBv--Asu68V`bseK2a*>9_w&#SsliwRF2wF?ZvmJ@WK9sGPF&_sZMybNn4mhsY z*E>j7M?-$(L#shw^+5f9xVI|ybRz2xzjUzK54D{qc*AO!Y&r@Yr6^(KR*%idO$=Y^ z=cC-cTH#3X+p^(%X_Qtf{j&)ox1;?kVWLL}`!-RC*NqPoQXyUq8JaUho5yDg^cTWT zgRn?pZ|D5WfIPkDqnyU0T4E({d#P_&Op;*5L*?y&on7w(Y|v{ez-Gy3r=wGfm>1wA zsCCGTDRm+8m^yEgqZjSO`WhGcm&<5+0uk-UNO-ij4{5yf$LLFP?vv*ywM57|bD4wC zeYptWwix%)&77+WJAe#u!&!Rm<8WB{v=sQXc`V%UreBH;b680Zo=;Z+fwWt~=&?B= zuH$eQKkYK|!vDDW4_9WF{<(H8kD1Y_cV65{3w#m+$H>5ou2mlg?{7*`gO^KAdc&xx z!5);vr$1~@;$)#{vcn z_x|>wONCK!{SDvJ>m)w>f9P=AV&W7dxWEFRp67iTn~@yBFxMtb$(@cI%XvG7*PMBh zJHL<7=wJJbPG+(DaqrheFJssi5*-hk&>F#lC6x((@un(XSG&0{yp`)%>2DCy-wTX zo7aT@&kDwa#$b_4@D4zzrt~W$;qimAdy}yanDJZRSFPM^dw%=7kCxe_VTIntBKnIe zPQduU+}~@Us4q?Z24^|(L4G)RbKR{9ZS8Ki++S8pT;8X#=#eZ>2}i7czPH2lKDsEw zahDcS+@-dMsS?MZtlED7u&u)(1URjNZ+6YBFp^)jC6C+EZ~TTG-!sZ^D)8^;Zgw<@ z4{|tB;2=3<2*cnp5x-cIofKIbHnur#dBWDk(eL0d z8i_uKK zNcG|5?$T%2w!mKZ1A}p~WCLETt(*xX_V!1#b;bWfst*Z1xe*5<=z8c=U2uYR4nn5a z1ZAy~Ze}ICD;#z~rMtLdBiUSJ1nk2Uf4+{`2}rTAJ&uEaIv>_xVJ|$%7rI^r&VXmz zez3zIiPzE{3{NY|V&osqB^E?&>li>ftgnA1@_S!zf)VWs7K>n+(G|IU>hZrgfN0>m zTSBOzf0`;}v0G&m%Ay$))sJ>jHI{u^Z$Py|iv{BZRbw<`-#GjDq{4HKy?X)?pB~E^rC)7^2-&e)Co$jouH-BwPD%q^wI!;um-z z4e39%zBuQ#Cw_^VvMB&=cS(4f6#fDz)Ia#Nhl94NL>pD!A73EmzlsmB4JUvf)+c82j04l zgg*EtM#qhtRNb?HPUw-IcWG8f0@KY%oVc$m!h3k##6F4RheLM{AAwZI#IEBjzHKeA zfrFddU5zC+rvqllx^tAP2lt1`HCEYSKX2yl_5?#{T=D11M}KqUg$ptyzY+gC`1o#m zU&IklYmon)XtXd~L;*N&Q)xvBrepD~&jMZ@^8+T7kn!3i?pt$>s-Tdp2Ovk7xSVf$ zd(718O3rm*>yMSFP*I@nGx|8GNXhavKO`G}?Ss6N#aX(2cXwN_mu3Aq6+hlywk10| z{No-K(*pKs-Ajnz{#d$DOW3P~X7<(!hADr>We%Ou{{0^|-}U6t8|4hX*{{y@!3l1) z0I`WJ=$8=?%CHo?kjM&}nCri3Rq~x*?mT2K-mP_zQl;j*2>DU8m|3CA6xX^AE*_X4 z9DTmG-1jIS)S2TePrS+@l~%lxp$C|M=+-sZsr~s><_PZoe3qxGN^I}Km$3sb=5FqgRa3(I$nEORc3$Ni^F67Bb|ufeq}U3Z!f z?$c_2GmdTNb&uN{xj`tpt$0^or^a}4t_sQ=)-~t_fw}LyI!|6~)Zgz5r=FU=jR z5PVgF@3lMtbbC9V%Te#Sp|heU7Yg?${j;`QRcf_InLjLEHFkYFbKw@ghY};HZWWNo zPMamaHD{T2IvFN7WRwTUPfUmF#lK zT=UCDvLlWAAgr&|NdSaF2y|mlt+~RVXe&92M!(q~x0)!iY=p{~RZN5X$#@fZL9)YH zJrQ{q7FmQj$~?F>LvKK0b4{$llN8H?3Yc_4pBPO3j_#?jwhMPh+6Po{4Mvl9be=2vT4U6Nmy^Md{pm#RUqQG*+m*5jHj=Dc z02u~9f&+VJoVAitPe>)Ne5jp4_`9pq9ZZ%gDTcVw=Too}eZ?>2&4(qCvqcLaudi|S zo?I$v03>9Zqn{WcE$=tA~4tI{WTSN%{BXB}oi0RR#DmSs*hj>qkj%OlOuJcrSt=;nYhAEwMPus!@l{-SvYO?mkVh zv{)vA?kl9QE3|`m^NV9Ck1Vh$%46Pb$vC+6jPo>}jzrC>fHJe&;s2$J2`=U;MBvjW zbROQ#Lj?<5iXC9dRn2efH+8@;9|{azcf@W;Jf2OA{3|kB%2?=OKoZr|B&2ms$)R0N=ng6T(LMxNKPl5WaId$b z=tb|noO|Yo>mHKPq74qVTp4nM=%fcP^(wD8?^yl!@3;*rFJ%X4GPoA-frOWmwCVOg zqd=$s-4nwRVv-#-W?v*6N*XXWOkHZ+R&wHRz*#Lvmdblla*NtM;TTFy|2tYH+BeW} zzrZZUa5y=@zFv4x$z#Zd1WeHl;VF=ll`MXHD0@RtNH`>_iuK%x&v^Ger4 z9=d88X4hXjtNspRb;&55(`Mk@9aQliVY-oy>Y!JUzFS#-9+UL*waf2ewpxv850R&=Y#0rU5rIAS-$s*!Fe;3);Q~~#3{J*42x1J@A zkF8E4`9WbL zdXo{C*aS%#(4Wsf%TmG?;q~)42Nci#&2c%zFgKdL&n@>$lZ*$xZh-3%S#}TIJPg<8 zdGZH&DeP)gmI9Kl@ri#&ki7+868EH&Q&)|#*n7v3%RmjXyMfyeQhb4_5HaNiDd;QU z4ML6N!?PfYzlu);;!{4n9qDG%w(6cs?F!Gr(sefi1b^Z+w$El@g*#h3#k|%|nNHj~ z_}Pmjh>c2}zc4DUMctu4~hP?Oz$SS<3p);nffub3ii?*>A1sj107CdnL6paJdi7as%`qO)>&ttuY z2l4z_d{&tMs8snYgcC=`h~?M&ysfmM0^Yj9rgS*{ra=qnYxZ+_$=E@gj{3%W?_0+@_gw>xXD zT>hlpVX39`XNf#>Gkmr%ads=FU`u`K`(0hy_IBO#=D5!U!dJ7q7`~JIQU=Z@~0nCHP;)(i2 zIvCVJ+9KrfLDtJTTg?y!_AC?%bNrn$vltazZ48xPoT5LkGOof+H8Tg)S{<0jUuYtQ z18_sP+MSyt#A9^F3`<>Y>O4vx}nisMbNzx6@*9_Se z3B|+uKH@TgTAU|cHtl{buae;FK1vwN%oO*imVMn&XSnOWvmnbUzmiQ3w)eZj7rSIS z6qz0VS$s_{&B@B2r@`gi>g!<+F30dy)iaCQ37}oQ*nF;|D6NxRir@ZJ3m=^J`#77a zt<@fdLA}=Lg&Xnd$@vFta=$*$(}8Y1Da*p8J^KB^)o(`uNu{#lvKzDCYf)UCHSXBw z#`9%M#K6*VGq~vd;D+yV-h$*#8LHAzO|AEkv6qLBHJPDgf=-|fu|VVcfd+>LpOEGX zH)o~_zdgst{T-%uufIZ+5DleP27ivdV_URM_x^8SsH?Mqct0<5%9Y(S&6$P%dicOU z0LG_o>)E64F<%IPjRY`4+Zv0c#&~A&Iy5Xp^F3`h3`G5UIK0Q%#=KLs6|M@H>YcT4 zOhEKLG9pWN53eD|VT}A?f+jZ+J-g$nA`4DzNm6KB=Ki~tHa1}T8f?&ljwYmUi>St< zA1xF?%Y|~w0d#p7n*e97)(rPHY$&<$&+JI-jjB$oN zG$wDJcNO0}-hRmEq3eNo<@OLvy?iLvciZm;_t~zf)>cuv&%4rd@aK7h)>dM6Z<$4p z<40x{J13vLDWKN!z+9XN)wrl)&jqM#hhat)3{G-TG%SBnQyDAS=*-OG74+rMA3Cr8 z3L%erjfnK}mdI$e@SFJ`v{)@8JJkSEs|^B*x8F8UZJ24MeZNEJmqR`YXFKqKodaJv zG`bST;J{;)sj96cqL-6|OpR{p@FN$Toc&MgS=09_xN|F}txWP9C8DrCRhL}$4n{fO zL{73`pr`$q_)csHl2G`M|Iu6Z9!B;U0$YwM`qx&+81Kl_C_xPVa6(ce(u`eqCZ{LY zKixRG&S%xyhZ|Sf0>I8Mcd)M_!5~O4wqd%wiI-f!>rN;B&&YqLTi>0z=f84SZh$2K za|==>tZI3%Bhf@)Z$UcOf5eQ-v3gE6m!|YBkiFkYNi#LasJ_0g@jDHMj+b%n6Lpla z&$30yQ6A}g0l_A(yh0ft3H0Ts84@EU9rqToILNK`3iD|5c0GAR-jh%N8ul*X<1|ng z)OP*{XWIorh;%dBVz$luUyj!78&olVV%+m;9hNlaKSJ|*^8)yUB#2VrTvc@PStLJK31ZjkbvIVQ%<7kO19_L@78%f6{sESv^@c5zN_#K$ao34|N1h5**Rk^` zHnYIxbl08B)G>SLzoi+A<5wRsI>1{L-{6<|oemm8qQ%05so@XrtzG6D5Bzidn~CSk ziyoKf#pw8s(qK+rz_%D{FeLygJ(hMsxqEs$yW}TX7jGk$%HMkITKRz6f5Frv8l|&L z%6<>9599$OF9L6gCu18A;b)oD3?1Mp5|dy!Gh~{~zr%Chr2QvL>%`a#qtXpr@df=% zyZ@lja=TP7+o6@?Cg#R_sNzUgIwjX-2j*wPHo(rosoY^^`0r8m!&MZs1%J9qI_!x2 zpnCQU4Q~7FQp>9x{QwgUyrrqMc}~TT!BAc9PM?-)Rc?mGkn%?XT@qW2K0x~*)ll!N zDka0pkJ;d-f6PM!OwJhyd-%H#&_;P?JFTBC3_|-tc|O2f00i=hQZPs|Z=(?38sMUN zy~fmAnEzI`?yF`KhkQL%;uvK*<<7_~61-nRALg6uB6mCb4ov~pbnr|?Y8*oB@}ZJ! zt|q*IH!!o6dw*#x6h21}UPoVz9WU(nMbrZ01q4U#RjO8t4SQyYj^O z%+a=vAiSPQ{kO;Cq1t)I6P&mMb)kwtz3BAaixrSE@x2-X^qT1n|4o%DRa}j3t{z~G zp{BWPN;B{>e>K)Ud7&a!0>szMzI{E=+e3iLjIjT0Y+!gtE+a2!FGG#sWg&6tSzWOd^*>~A7XZeez zvO`tdg>-{W+>640KJV9I9O?dZ?BM6H1|A)UMKQUOtA$jfV*T*w*6BYI7rV8_O@_c> zdBAn&kHwph81t7Mn{yEiz&B@GdaN6YYs+DCXLlyK9)h~@{ikUy9H|AW&e9?~ih4|0 zOE#V|&+WR`pg1Ln!oG87|=c3tsuPHDR7^~LfuJk;`jlm%5+reh5c;5 zuv3WQlEYs0*GHb=!ibe&eEMd9u(s~8P(`TU{}Q2uefT}~?m5_inF-?2mo)$Ab^$Ub zZ zBsyVMo4@uew%8v;6 z*7?P?O(^rWO{B0sg|eB{g~XY`Yhals@?Tpt4^;}1cC$`{)}vp~n~Rlm7bNHY5x5gP zxDit|%3m7zL_~%eAe!c721C)sHO6q-VjFh;OFoj#yFU**$?RpCnqw>I(x`NS%jlB# z>@Wt7uWUSB|E6(e4%V-=(fy`7;>IsN8H)vO9t&Rato6r^zd_Kl>Qk9q0W6Js8-lZU zeSp1lLROsdqqMvmQw|u<)9oU7tV(M^>SvN9O&<_oW|Eop>t$tBQ&DTWi5h5+$veA- zn`wZ+w~$O4AR7%(NMIkoQ25HP-!9|(@@0;V#H!?%#@ca(&b0FoLOk$*zb5cV1ZB!= zgCI`fgw5RsamOng#L|+a&FdpJk}0&GbKE9M>X2CT13KUJzx5^CgLd~r+E){TkbL78 zUx!eVmGlefe8`Y}-cSY+gq{htcRURA5Rd zI1ozO1lFiF#g1=2UavgFZVyjab&5+~v1Kh))-_Fl*V8<7Rn&VTTMzA;E)tEIe4*Yb5Gw>T7RS1dN)%qF{ro<9>R_@s@WGtx1-Dz2YNXvyM=(iH_wetCOTvVysBOAj*W z&KcKnRfBAKZ7j6hPd!>&L!04lnp-L2$Vga|;a@525hIl}C~mAKb?4%_HF9g_^z%r_ z59+umOPlJ=iCKiD%cI6iqW40cH?aB@e*T_?BCp={EO8>rm>K%Gm_W79EWb&u+YuDb zonBjlQbBucs;P%1!0-5%0+m3Yo_A>Ag;ZeYR`bMFj{TD-_|LDg)Q!!C`(0$K(*78P z{x6-NTesA+9^)iZS+l~=+r@bErKL=-uC6N7IF4>q2ThHf881-G;!DyHA*_Z=&8{a5 zt8mtgWbN{0kH|Cj%h|9kU%Dh70XG9y{jJYn+8!6Eml#1!c;{f>1Ks=9YN=C2OL(3k zHC3|yi85Y1ykufum#)B&;I_qWdjwAok=A60!3SCd>fL%Jr~cTXc{BV7 za+M#v1b^V)IT-kBbJirD`z}9*r*(SP1Xjq|#ws7B6G zLYg_Yt-Op;C+R-_-f5;?GJVZ%7c)gaeGHb$w7uH0wNOm?*6dT@zp6gi@l$BpWO8?D zCBki7)9|@4xG?BTMW}?oBY2kW!JD1=^=0G-hvHFE>a&!jZq!?swgSc5bI(m0hjkG* zd`obP?nX;U6*3dx@N`K<+7x|=XU^8tn=hmKX9V@nBK|#hY1U^1grB|7=^$7$@ak98 zY(7)m@@b95o==A`QgbZFBdzr z;29W_=hejvrqGUuI;P$_O@jBkl{EicYv+LP!{F$l$9Xns*U8xGay*os%U^U# zc=MuVL^hr@@x>Ztzb497@&po1*eOzyPDO126yHAYhTo<&T@6UH5WKI;Wbi-Qev30w z-&omLEXAo=6Pnu&gv*d+p*oRo_`h^x>*7cAV{8Nr-(JzSgFgSQc%(fD=7QGE;ET;V zU-(>{tQ-M6AyJ5kiNCM3#sS;Zh7CdcQkg8^hv64$80(KO<8@%ajRg*Uj8iOLK?X8LEEs zFDSn#L&rOU%M#&uP-cBCsg~C9_)zG$?=(73dFAPjH4vMSCki>^e}p(v=qBYGae!mO zaqNsN+-TP}Jy!!<&K5Ca1civ%RzD%J!CpD82kA)+AzQQ#I=g^RtSCiJ;i7uqF9bzyb+(IX>nn!T(j|7|-}B^z^7?VPy|=)QEyi38sziiUBI zm%>yH2SXYjtHEj^y^`?j*eP&_#rDb3_5qWcThG3?6{|q4c5U0qc)|V^x`63PnDBNn z>A+~;#^akq@!6EXfmEQz`1?OzFgz-Kl20M}<5!fHDWyU{ z-tD{_f99U>hC3K-wl763)J}-3g8Uw5u56NjHcccz=*Ke)O?2sNEW9g%c9#x4M!*)? zW4LThe~q(wM<$jf+`?^&d%d27?_yNi2j37?rRvYaR)hoi+1Hk8C{+jE?eEgTz)*tM zWQzw?I^kapyU8E9+A{5=8ouT)G6Yn5@O3r0Ym_)$KtlP$K1=TnYC%0L`DhI z^X*o$suKy7Ep252S|Ayg`THH{5P16o8C$lHJ=$QZ}Nbwofi*!W&vbw!k#P{_Ar? zjO*HEJ+0MGgYLX5Hi%c9R$((Fm`ifPRlpLi+v*MA2_#OJOn&I;)#-CeZUbfYbdm4Q z{+!yh2+ouUJ=~+TT}ji2Gv1H;5}FNjUE{IM^`T(VbGgWx>3Pt> zbla{1;l(8VO}U>b&Bg)j6s3(bcmvynWCo;|%kqvV@0O^{d|K@!GlCi)N@(F9d}^2Z z{5xpZ_6=lX7MN_%GaFFFf=#(#YLARtF(i;Qi80w6-=AV|ja}DMTELE=`scfzIbdYc z=)YgP9`t%VjWHT)Zf&jTV7t(_DX;~XfVka$-PfK1$JQZA;)L%Cej=+mW}ljK1d(PS z;EzNXlE~@y`tmppc%Cz7|MII+uzK!`FLZr3!GXKI1T8L}R_Y;K>CLBZM4-*Q z6sK)|K{K6&!4^FD(3a~?VNocGR>8#8@n&n{R~qz6m?)3b4v1*f~mS?WN(AZK4oQO())BOLYHTZun+3%t~MKl z`*@QT1^%k7lvp@lu0$e%eY$Z8-OccvV4DT%m#QNtJ~L+y_HbPfQ-DRhSge%XZ^ z^(S z#W47BG5+A%LNU9FgHNJ?9Fu>Z(h@`s=}b~D61ut6p0gb1`{Wbwad(X>{kO2<$id$^xthVxi61E~L(V!F z&SmN;57+F)qcP{&M7R2+ryGPf;6%*@BcBMY;z%{xs;Yvrv=xAK2k!sq&z9wmZP=>2 z-*6whng-vAHm#JOY7=~;jqgGkL*@kHeirB}?Iv(Zn|1S{t7%-Z`0Kq8H@#^tH_q-I zDDhJ6ZbdcWmsVZmo$b57?NTsdG^o+(bRAC^rKJ}VFf^NOMs{1jp`kQDa{}oaT!@yx zhp`r`ED`kNc1k6kQVvR$84H+gFfK<`o|D?G)c5AZ#$FmaaU$lc-gCTnTYAL%aQ~*% zDjMzzZ4W4jfZQEk(<*&IiHZ{5Ng34?MnSMK4=&6~Xbu}0B7*)lk<``mlXw!WOr)2O zMeY`(a-K%B`{cL32`3M2xQM#nz;mkiNYVGvRXa;}a;c;3=m~5ZmDKDP^*QHRV3j6W z7=}+sFv@DVw6%0^+>0EI*xMg6v+r4kBFkog~Sz_OS30aVVRB@H}vy}9-u(hOuM_T%|lB!*TsVfz6on{yf9eK?t!Yy=IDe&mw#=WL`LWv)H%#h}bX zjObYm6Mu`bMWcULGAJ#0h%JU@W}9`J>25(RoDs1-Ct7<=jNlb*rPU?8YRM_nY*P)? z?niFoFf$l4y*FUT9!K#I!84`T99Ea1>Z~R^*e<^7hzTji9@ui>k^amuK?-Uj4F9vl zd$EmzY-am=vLN=b{QXONEV^mKH(7g?~BVBrW!6f?z5#-* z_{F>)c?|@MrU z)idSl9A--!M+pJa@)IZ=Q*H*BCZJ0%otmOf2BrD(tW+b;KR0J04fZ3k^m%3wP=BVI zcGAq#`N!}?f^rLQQ6-e(Ae0=C^3R^;H@0x%hzd&WUK5@NUXSg*`fBd?3?7`$_=Zy~ zI^VzVEm5-7;UjC69Q&pC)V5#dS5O}9Y)f~Bq1I`wF~0$IE~M5b=O_`yOfd3)Q!NbK z=je~9VLB;wlY)L$9}}lJ^k@E-Yg5-y;p{#xE!*Bm$_x5JrSZMwGl3e}kU~)9aL5eHK^JbCAc(Be9> zD~`T@a{nX_LGd}(R=S2hxj zB7_MaksND!;G!96@@5nwTsL>iYk811K9$;QK{3)g*2eDJlRSYUt&`^Q;5Xmh=#gWk@8&J%C2*um5NdF#iFC0(*_VDG#b2qFhODsB`^ zP?ErI(m2bvorR$+C(2MFJdbeo2RN|`8=UU_iX0`j?O&`;no%0%(v zz%1#0P__Ni_b417y?Lfn;Ng~_R=JTe+1l_h1m*)UJ-)4OoefOUkO0(;J+_fN0S^0ys?mv6t zmTg+d>FO!7RG~kEtdQ18&!s&aTNtSN4A9f{NJyHP%&i$OH1spx-&5HoCR*vnwA%uG zAX7H{qAp%Iw#;KUKl-i^+hkvohPsy`mE9$ytH(p4sozpok7?Hb{*~FwFZ$=hgnd}! zx3wz^b)3e3>DE?=c9UcxGyE4!T4nx1JT&HDWnpy8e~ePhA3)q{Q8{KW+F}eevjSYI z=*zL%!r0D7osBAm&409Peh;TP-1irjt%dQQsYOuQLby&hrX`Vj`C%-#z;^ zV-q7k-U^g2pK!R(IA%jKD}PYmT3APvq$sym@5cn1vg@a~oi4k4J=kJmw}-B*F7AqT z!+u+Hxnh$Ti~U>XJ$rRVmCg+_6O-0j9J5XEgchh9SX#F&|nd;-`F|gDymR%qDo8)3gDd63F>>k*Zly%lg zw9fPQdb%F}k=au*h^E${ck5mSE2^OX`e+F!eb%1^)F*&`{1|7O43C67nIeTDR6Q6; z+>#zqD1xOIwyR6WZcBRh!RYBmzDz^o50+B3Oxx!_lR={Z_d&X?aV~x10`33lLCvwE z?;1Vjl~YxWMlcl<*fh0BS8>oX?Q2_=g58p81ARD*PD)3-+|>#syT*)FY=HefmD5MQ*N4f=)up=gm{BWJ9dkfsuNo&lI4K(QDSr1yP_^DVF1vslMr7s_g^usHqiJ z&D{M)Pn^b!FIRB2kFyX9Q`AyQ94<#ON$bQDS`gw_$B22!yqwO`+I-8uW?EFO_gewX z>XftZY(Ut0FbPb=Kqvt4B&3&=89XK?cd10(2@+re?%?4H~}N5Y>m96OYd+ zCb8pQwJ@*uj6=Ou;o1F}He>LCrX*;xBwy{{+>4Ov534{5kjLg0y7e5K4CmP=!iT3( zABdUjjpGTg_VE^~6}7M8rjx-_>WoRQGYX>gtHPKuOVypDU4-gvPyNGij}&ewZnNcw zV|RJR_S?4pCrd2TJg41fO4;^RSg<-Cty#c{`^@>#k=Kx%*#&&qEmc~!s^_vh9=DPw z35_?a&jI1=(|Aj;`D=9vfF$lLv(9nzMtf~;je33iQ(uTStfp&3o?3H^26`6_b4SY7LV0zz~nr-f17L&#Zd{hMtw1Hq)?xWGwGn0&RdXxEwDz#`hx- z+Gp1d;e1!zYd@UF@eLt&Q8mwycW&N}_B5qWMWK(BhAhIK3(usVi4PZTC4KuKH&60+ zPv(@LT!t}%8dT_Z>kW7{YjrU9s$D)=$EgxOPvjmAe)m4UWUM%w?NbPn$kFq}gI_M5 z+E*Yi7BGvq=ozQ%s|eI#pJ5YRf*vM_iOq82@js3HGk=fIrCq zoVe7>y(^J%wZaWw?W>`{sjLqTQVA(Tt%ASt(4~-&m*k{hrO=zMTv9K(IXdP+T}@az zDmFvaAaO~*DB*;=Dc0S$IKOo!t?G?$F8B6%9Cc^19xcf<|aavy1t_SU5gX$-eS$B|Iv2xMft07%z_CQ^0>BTfN>*6>n z2sY9D7X*hxuzh-qcFCg1Z>HGMdYnlS1aNiUh%fA^WZ^wI24D?cm;8Y8OC1H1($xDF+qE6}YEtpGd*U>*m9-cYl=iAKilmI0SF`;m{^;-nyW zu0wDAJ5iR_+>tn87@cUmwROhRS)taXO8efk-I5W!lF_;(d4Ao8=NVHhHPl2jRf>Id zPWL-nEGq(YS4L}))svdTaZk6Ug*4B&%#qN<<}~l>21pjs!+^u)nPgM3O7D)TtJTNTcGY718O^VBVd& z*@qeZcEe3^Ze&rt)@b{7OQFl#97qtao2o|Q&Lps=V>;XcPD{F+ZrO#AXwac>&YM_x z_b!V4;30fvU-tapj6S>BG^iH8#H~)=JXM{@uOcgah(amZ00HhrwY|6HikQ=V0e*qs z8OtB@w1$Y4FH7|G@lw3A^EIJ(sgENaD`SYcVmz|M4I1j1rh}#W#|1XG}YsB zT^yFq4UDiLW0dHKw)R6Es#i1~gQG z$Gpw_S~FDRIok|VF6<0KW>S4reiTG0RdQpjH@uiETVvE;O0%`f) zbBHV*G(4EGSyWECed`#DOiSXHCP=(!&dmU^S1nKD$p+)p-Ym>O0#iKKpDW?Rd%~Ft zcoB>q5xgo0TkYq6@Frv|>)u55jS`EIWBGAm;~kv78s?&oJ9~P92ED4z*XixC4Bg@c zF2imEh!A0WR5oHgmYj%c_u>9-DR#w`v1_)VOn9@+=(nZ+v~w_M*>C&TxV(C6lPH#u z=_SO%qqj>DC)y)ZyX^7SAGsTi#*YjkDHwPmx4g;2+wn@;eQ2qG&K$w2VjO^aTF z_3epI@rp4dVhNAw9IuCD@t|bKF<7Q7AeqYFJ_C8NsWU2$VhX*4>=`d_FH`K7PGaB4 z+?j{UYl{c+IDTJDl5;kI4JYakuylayS46S&6pUKaSyzVsWUChVj_;U+xUjq#ib+CQ zUzl!%Kg2B@e!xgSE~o5>h~8Jr4Y_;kSJ)<{QqN!=S%eclPabedg%)K(l}_7vP&*WF zC#+{YCxWHbpt??0S&sRsrfQ40O4(UKc@qfayVSHgv~Li`FyJS~+UTz!a?VM;uX+Rc z34QP>JJS^2@oz;fU%Pt%_gCJA=a1mU&94ka1Ek(4XxmEqtRC*WaIupT!iS59@mQWE z?V&@wmh(PGJZZ16IamUD-_}~Guq2ogS*;@_RVcqn1K`Ax&@rLOGDIp&G49Le_+SJn zsd$*cU=*bFz7{9aXR`@`ejx-L zA-t@V{y?eYuS-C7QvqD~+i4=FuY;s($lIJDA=H4OTKVXXt)Mp`P%_jzl^CW!F?YgX z<2A~V6F$Dj| z8-SZQx`K&@W9b`p-}f`Mw@PF9cH8t&y8H?{99t(Er>mj1lb(~vbMTcH3*oB0*OB!X zq+q<~O*lQKXSI;(o3KbO0Kygao|Qop|9eKI?5P) z?vQ7gw-JA*NEyzi()5y1dWWy%rUUglQbvSNBam5CJc|I-Wp_!MU4z5v*|8UINjaJr zlLFB>L!$<;4E1=v)T^TrK~)*b!}6-yJqs1A2BBC98rIDhyiZ>GW6pLaK)t)^zWjnv zq5(Hq=%Y=~zRy9(w;U=Ge8z)oexg2y^HFUSP@CxA(`sslwZQMau6qX-=`^6T@!KgQ zAz{Ix9!I3mc)=sb!06iQgzJtJ-Jq$P8G|THaw{hHT?u#O2=+h59B^^j*CZ+$V<_KL zbeppwf8|(;gmZDi;0nKsko&DSm8lEbmWyI)XtRHWTzuzWwa0-reN4A~ND?MrKKMR} z8+}(GoSiK|vyA-B9)k;}7uo5iT(bR0Q*pWIx`Nm3l90ygzF#xiJVqxFTW#GP+K8xC zUGC~pzl9>B>*R&6N?mKc(ZeVBUQoCdDJsuV`(wD-qRO<3I%`Ah=fmA2p^HRy4b+H5 zBULPH%d6xdDj^r`pbA-SlYxoQ*L$=4-UqImNiw*P-v!Ten%l$5HEEmZOn61-*Dcd_F{WJoquGce%k*2CoFt! zng}TaT{MkQ&s!B0v8W0HG_`Oi9bI_8#h%6v={jznt~)!NiP3TPHd5>esX_H&2Er}R zheo7T2ssqIulv6rMgg^+U(}^Kk$;BM$BK(w%9>qdvHJ{}#8L!KC;n$39h@63uVP<; zcU!JU((2$|$T9aFzwkM{31p1v$IpNKxW?@BbFmhd1k2b2KJsdH%|B(f@QvoW?m^%K z7$g1jNKCW7pZ@^@nON+@zQ%tMpags~@EUrHT}H7(qB2KoyKl$#VGp{qdUO9Wf)Y3o z3s1@3Zvf2c-jlX3j)l!M6cXl@7dr+lE8@hR-lW^)>N@4AL2DNtU>E~EZC7ox@gEe8 zZ>_MM{>F2`msdW3m%A)A6QY0d!INdzJS*_ExRiG0I)tKEHHcGHzy9c7eI zxcs*|MwEH|TT!t#1D~f@QYg>TbKvm8cf;b)BZgabdkiP=+~YQ5{0!a~qLyD(Gptsm z;Mj-SB_J@goTd*((znkroXcsTmRv%L{XMj(SE=^X=-VZ3YIB>) zz?i~4CWY(sxAd8Mnm;k%*ghq*EO`sib_AED3^r3K8oLvB&{OO^r3pV-zI9LF*grdd z5Kk|WJ5H%OFn*_bsV}T5t3Jo`=7<)thkJ}PQ=M!Hen~~Qe7M&=b5}}{1Q*|(snR1B zi$@GPg%h#u?}ItC50x@vl_HUu&vvv?ugq?jgbw0c74Bc(cVg5b901~(IpfSuz7%Y( z&zckC*N8@Ntq}e?%rt=aCCKL9WA8Wa^6j)Q`SaHBCo8azUsn2RU{%j&vb=E@A$qE101<=yhtTt??;*8*^0cbf(6xxiuW}M*7BUymqSf<5rOkt&z8ONyWYj%KT z_Iv2&^UgmM1OGrg#EMzWNUS!?&r%un`v&gl*7dn5ax>>Nn)f*F{7Fqp5NbO&`GfwK z@3cz*!ymcw4(y79CeVF7Zu45c9qzH6nP^+&ZX3c7cO}<}Z(j~@K8vsfNoBK=+k!;? z^2yTXC-b&}0W3TtPp^KfA~mW`s$>P}9K6I*mEYL|n*QOf`s1>NaIhnNp{z#th}fssSh-uOV~rk%v06SonOy*BKr^hV9nJri$F} zF{|8j*0=F3aLqM(kfxU?eqrl2b7Zs=Vd;YEnU?p55SPwB@7g)E#p=^);4N5!i_pFh z`CMr?R>}XkXRmMhm%sCE4|K+rct7L2_mb#50(`t4jopNFPIHr%PUbon(V!MU!P1pB znn7NQ0kvnlZefgB;d$I;dG*EO00@w8FlG7md8@@C%EA@S{!QmP4>V3ZYA-X~fsYD# z##HqGu0&)1R~J8X2#IBBd8o5vWkF(ujWsxG$4S<$; zR!@%le)rj@IO()8+@k)6Tt(OY^&Y+`jq*rr`Wl9=9#sa<;vT|;v!o1IKg|2dT z`!*e>PT<%QN(*f37YoyXRwoDE5=V$oymlp}h<0VuUpe;jsAsf4+@!;TMUlwM%!N0n8}2w)rXnJDIIqD6^%m#q0)I?4WyL9+s~c`)~JF z$00u|fR7oZi)XXygbJo*qzUT?L5q zEr0MTRZ*p@_5`-;NcVf)y~U;@ojwzA5m4Zb1q1tMsY{XM=Xtn0W&$+6+Sa7efgqius)gyzh_LV+o~ z{QI6`>RP{8Lv7{xsBxiS(d~AhRQFk6BJOzv4`q<+uA?STSJhN881A--#SEwaW5SpW zdHv)CQdk;AteegF;{^sqFq}>Ym9(+eEIH*PK{5e~=xU(0e^5HAu}P3_i|4$8GgYJf zOPpR5v<<^Dou^rI8LLB*q&07+BW9}pn0S1SZns9KiN8)t=(HkNF zg{|jyB43^ECxp&|_EO%OW`bNMZ9#q=s`+Qzsiccs_)>vX$c#v`|MxdcL=ld5vR>zv zVl@%e&xpMs|GFcz4V92UoMk}Onad{iUahjrEz3v$Bo2QN`S*=LqWMgJPO#UMui43F znwC6Xvv;d>tq06OtU0jsxt?ozzwB<1l`(}|uIX3=&^Id!XT&kEyPLA6@SrOvzSdu@ z#Z4g&u3ruc&Pb+I&C?$|A(dof?n93if2?L5GM(CEcXv&dr7hhGy-JCF*zj-A@71ch z+>$bN9v2R2t#(1J=W*n8F-B$vdNiZBKA6{Lef){iyh-m}C4i;RcAC@EAJr=vowTfz zJp*m>X07`Oav4t>?I~O7%6|(9Arut_AGcDC{xXt`ATw!>R2@(hsmdf9$VBv~Ie2?x z#g-t2Jiy1m~T+eL{Jus?7+pkWT`>qvx4bO74<`O$1`O{*6Bv|O6b8<;qmecW z1k6VZ!rpW z@rnXWP21{`c1oD9*w*RQ8;6&rLt4m@f46*DZIyWHZ4L6@uF#s}zfVP$ggcRrzR^=p z?)E!prR$InhD74~0j52z-I*(!TmzIibFof#wn^UTyb}a$wx#_F6A3u1c;~_td>~U(@ADpyx5q?suLuu^24^*ec_`!)(zxxpb$5d zg*>+{{6o)^Z#r7FYg;b2>G0TNkjI&tY_MmjHZh0XLS zQrrA~TPHa!$gnv+$Unq2a~`ndQ@RJKZ{QlKzp$kZZrne=;{#FLtp&DCr0070y{=2U zav@1@T`+%?mF5Asr(Ia<-!Iz0r#P`M$=b-!;oJi+Ffi|Pswo81K&-mUCcyF?H#{QZ zAs*C5N3Q9wQ-iPePDmi~UGMF@f-O+&PG3K@Zb9u?OFmUJs?cbx zNwXcWI{Mc6^R3$<=e|xw>){b2PxsS=zf(w8C?6ey;@w9_PVs>I&?PVKH9hYjb`Z{a zH)T!hMou!ZxFRR9&^}e|nO#^pxAXc~{gnQgfCn539yRd36AUqnk-uU;wg03xL`l>2>u3i@@b#;;t(+FQp)u2f9XmZjc z`jJY+5oyE;D%1(08Pq0eliy`j(}sfU3dH%2LcOpMpY1!<%I$|e+2%7Dzdx=!<9O$$ zod>S_35O6oBdU*|+IJuE4O-0!1Nf@G@<(%0c$4M&ILr05_@yinO!N-=y2KUFxmYGX)zSV$RjJ2sNQBQ$NM}x$A&SD9X!D_e1ryN+Q z26?^3Ft@2U#wwb&y2CQtuM|^UVPS73leaE>^7D+hv(n;4Q;~o`A#zmD*B0lRj(Hh9 ziMyJ7oCH-(QhRwxmuT&X^dF-!Z<(SV6{TQs(~6`;oiX@0>MbZVE_N0|Hmp& z!Ur#PWln|wsXqqRb<=AsJ>T%NS#eo#jMNXY%9cF7^cQP8ws89edBE>%QN*IJVd}0S zn7$0hi0fs{cAO$-0)xy1VuSS2zYL$gumVaY$dQGb9?{A*m)NITWpUjX08gxqjQ*G8 zB;OH(1(BUVA2=`#6^wFOwh6A24GF@}kf$f+@mX-%`lQS+)0c%jiX4v_LoCW{(=yXM zVJaMp0rhOz?~Nnnz77-bJt6fqt$UVD2(k!Cve#W((1R@XHotJprHnp$9aGw%ZhX#$ z!W^gd!*dA+2?k_MP+&hY(dsV{8Z6NBzkO)K$ z(WCrH0Y6~+AA9b2AJITOW1=5-n|aT;{^ZxHdCA;q^7lgtr96r(K+&T@8mtj@3gfu+ zG5WN|jDY58Uo+vM@heo2IQ&?UIHWuXQZQ7mpS`si^J}{A4Rtp=N0j|P-eb9t z;cO)=YW36(&`54%y8Nf{%AbI4gJ0lk|HzahXjU?mtw2f6oW9q7*584j^s%>bW?GC> zE_S%QyH9ArT8Qv{&~!LI6_7(*k(hcbOHYGpD{17_y{~MmCmTr_tQO<^2zi0jvD1Wz zM>J60{#<)eN?b3CLTuj5sUt$-hkCU~ht|tvH9_dH4DrdmX(pc?<>ZFQz(WaAz~hi1 z(&(yVLu77)l-u##7z`RuK;uqiKX1pSY3QTzShzpuE-wld5~v|MPzW08#H|)eayNKf z4?5!5e}NS+Jlp5=WZ5lrrAIOyXNJoW!9NCb`BS@(Y&KL~URnK@AzJ95jmi_5ANaNfVDRrVVx11y_-!S|wt$lh^xuZrlQIM5{P&cKaWcj#;}Hv_25v z@3E}!WF+qxdD2^dieE(*zPoLSg+Le&?At^oPEoz&C8}2Vtoz@rAP*oFn5dE)bpR-Z zTcwF2`F|zJCa)>6y=Yc{&mMB=E@yzR0Zk{>Rus}lbqtz)GVOi7&wR4ZVpe+Ng8LoH z8TPlHcI>34*1bISMr3N2NY7Hr?TTyI<28sPi#Z^_`;RqdK8J-Zkmhgui3`om$Gs$V zX|jrB7KL4jh{Ort@s_+x8cQ$Q>dzv@{aLc4_%PnL3?1mcIVxS~LtXg`CcTZFZzHxg z`$g|T7M%bwb>}+o%-%P-HX$|Ke=Q|kB7F4TCkS?St{v|f^Sz?=3hrxF*d7bMja?9w zt2-bVv;0lg(Bcn}PuBmsDyaD9&acS+5M%xJz{x=XN^eKc8p=J68(p3mYa|qMhN*S=GCsc!EHy7{11OvW#4fj$0HS!x(R9P9kb96c1b z6{+|e-Za_Wz+%dU0^xx&MN$SX`n6OwQz;L=$N13GLS6cXdD!>@?h6xrPIpN$Ee-5K z4*Kd&sX4iFj*mc)`?k@}6Es{al>b?l*YRzQ=Zu$r1n*I=BISnO{m4Mra%GBGT704d z>TDZB8eZ>j*I%-Xh{dl!*0C)s)gUKCcbV6C?y~0l)1`tbGyI+S zWD{DtcbmCtb3rSaGrs=jZ`pKoli~@WXOoErl$_p4?s_o}cWn1xiwFkY>2H5r{KWaR-KrHxpb$HcrT^Y^eY4p*B-~M0>(df}SiL9DPYz#|vw}7!4 zWDb5^Q98oN%YEH~fedxpp@q7-I1l!Gd}t|M>tbMsq{^9Vj1*|LdAE4GcfUf#y03AS zX}?*sGziz4E4gyB&H!f9P3-vY{DOUcJILLohq!RBbxldkdOpaB`=YDkXjHE+qAiwn z^&?%H#Pi{vb1Fl?=b(kkEDt{QKEopj~%qxP5x|^Vdfi z`S9s~LlPWI>-*R5c_qoLuRZbL{?ne1ow4xm0Ey%gwdqdnZAY8eiMqbx9o2lRqTh@B z%FJl+?ru|A4qdeKC+3GtbPHx0a+^mLpoA`YY#+rj2c4Mvg*nyy`Rk~#Ffw=}^+WNT zEtBWfP#grsg-E{7p?sOdy2Kw~aDl15=<35gti9hd`#$d1VuCEX&e%z8c$CBrN?cp7 z=ecJBCK~$i(_zy1uG2(Wh>Tq5+@IM-(8XU^ODH>dXM0)^x0-r+J8Wc70|c+H&9|F_ zFpmbjp)!Zt8d2L-r$wyp8bT?t>NXGcR-Gs{UpALHUPO12XbZofzz|}4l9XLsDsDNS zC(#i@Y2n8SZTqp74zEe_55D*&46CY&_31{V$=qRLwZA@qT6FHmPEg6n8&-ZOnGHGv zrwp7|N{yu$s6np$nLf^^N4>{3N&*@Co6mrP0K@U?MkFjW-D_5@b_e#o<JK7d`-{p#?pH!(_1oX?KdK!wt$V^f{E8?BmRW+z6@R+kwk0v<0#4fOGB5ZP$sMVfK=+gwRv&nlG zofm(J64DqX=snDi(5J9`d^~7)6?ePoQ!ANycsFwwD=CK)0VkSKslQ(Y!m0}*gk+HnZYav&yR~)-&KU+#croCz_@2$z9@z|P61g0pf>mT%q&2x7* ze05(;81mXYFMMQcNQk`YLj&JZ5Vr2z&Y#sPER{5%f55{-xUUF1zP;L0(1>p9#T%&0 zUye$xMpFrNo0z63|80~Xxr4%i`$9Lcr+Mx)(Q0^?rA zWM!QuR8^-kRYX19*q!CZ89>|;h^iMh)Q3T>#-_scpT+GIVD zyumnA$@5Qnl0JG2y&31$Vt+}DBNra2xco#)({zDDXrynFEB(yy(#&QFMo%p#PYRJ# zx!|+xsPiE~hC-0sgzfD4Qm`C$_=LyrA~sZe9oMZvHTwuL>Mfp5?4*fY_M09c z^sLRrdf&!g@3OYW*t#X>Q{mI!RxwQvSeMilrKrOs8*&TSJ5UT3hTB)Oh{V>2I1{_L?^CVKIR^f{2ORm7K7- z&e{Zz^x8b&K+j3CtUX7KFlC3R_hQ1TxhSb{N@bcvGZ_hX%=r;C6K)(QXWEv$`Nod`y4Itpk<$ zcZ5&3p$ZZ@|1Xb+|ID&a#&B8y_SlM;2f)DNtQMMP2_(yFMj_B>si7r|O%I=R6`_Z`_a|P_HAOh3z%fEGji{H#6?Jee2v3bPb3Z@y1fy_&o$wwtcIx#q220j(APF+ zBZl&*DX%%kt0~~Oxq4uFPIOUQN@u!FM%6xyj3977y{*tB5a89SjPWkKI0p-QEK+3a znw=R%ASmlrC-VqavWR;0x??|II1u(3l1UA}h)e5#;Uey#HoD@#Xe^5jy_JTF+`Z0l zh;aeBOQ*|rqstd3HW(rN7WQlUG9ewq<*o zgyz)08aUw>i4lQn4{$xTZrCCJh@BtDUv7ry%|GzoP+L~vp*2E&k)v8{^z08`?nwQb zhEBEdo-qyO^SB-Ti#|=|$gff2#WnfO2vX+Um!u*wP>oqN;aCpetcy(O3vm#j1U#O; z+(b;%7>|R42V4IN)FI)FY;21no1$k@2nJvK3q!4n0K(u2eyY8!5dQv0T{#+&&-ZPWqUr@sro%7|-(BmW(Mj0RHPH|5rOd+>!yl1{| zrL6$hI-C0kpfT1|%(gIauA`;!><7O(9E5fqyz(miUp;MXd|hJPS#{h&vGu|oaX?uP zAS^{pt8|}sWeiacvpPHT#82Hti`uT{@3JAo&djBy{PV(M=z)_yKKR%1$(`VWL%6*C zJv5$ezcwrAauk zZo*5G)A(GPnIqL(3s(|uSawAOaiOBJdD-rVv+PRRjggcxjBpskKa#Yi1JCIZCH5$Z zuw`PT?Ofw*>@#lv+*^|9o^U4HCU-I^v-{}LzlOulKJN1FjlrlptF*+RV zmYdDVQZT$LhNp8KQ_>|^cljSd!3y=`-dI?!&Xf6}cbH2b0)d~Cme ztRb}eQm6j)q^2^25wK|w4gOhI7*4?S zUo*2KvEU3bKd!zGztneHoXTpNm`tLF*Y@|&G05r(zcqqt^zgGF+-|*G>ML_2RKylOfX!aQ~X>8I;} zxy`MavQAV|QI116jHkDRsMy~JNA?t(vYE_;HSgTftc8zE_w+;qHXK2hCB{23XK+0~ zS1CNZ8{_Gbhy_kR2!uQRH0~YXhYhS==fnY7z_*sZ7f$ub6WY${#|EH7=ih4{nmT?w zvFSf}k|UC_ojnE+`F^1Jd!2Pu`fMjk_rjpx@=I)$O@S-T0v|%kLzP! zg!)p?>p~aeRIQgM{VedOI97?{J!!ctXMRIa4;eDC1HH#(r)NdY@qJrI{Jr1a4|d-y zhrKlw<)_r{aZoi%ud*ljR7$ATf~P)aU0bSw&8&JM_(%Jy>U4KU>h+Di&DNMb5xY0J z2z$Wm{zy0=2lj8yNM+k}ba?N?SNNN5MaJLP{f=0Iw!^O=Z;YF9g9Fk14gT9_ISM)3 zp=c;2Qb+90AnGsTM2eTW4B{tY57^$jWr26;?#tdmo$CS)r_5(}7YI@tn~ z#y=30t=Rg|s$+<8VFAy7ngN0~iMu~e*!_H9d)jQ-kxAe?$RWRTJQT8<2+%i#iAMhl z4es$hjg34c;7rw@kVFYF{j~CC4OJ=6y@LypVB2D%(Fh-dFhoqL1g$GYS$h{AMk}}4ols=Q- zcrnHgDw7Nu4Tc1_H=DK$^Bg%oF3on;x6=jnl~k#}0o(0+ay@t#h_(`bg4xbQB=C7w zrGWBNLWmWFhQmGzbyJDwXM1)JA!E_brUQi5X8&N3IReQWZq2Xz9tMi=TJ=e?LKtFw zJx={&>|HlDgh%&r)u1#^Z{AskMu6f>@FuJl)u{+zoF{|CskT{ECbFZQU6Q{Yex$MJ zv8+FUQ#8_;l2hO$0^|T7y5)$Is)Q%XQV-$H>g08ObYAkxy6s8GUUhU&KYP_HvhhOW z=*6JM9_{QKk6mcw8ZmFWj^`Fz5?hA2$}13ft^7Shgdjb=-$R^Axi{r%4u6p!zVTbC zs*0~SQ8e&d%6R^$%s~RBJ`8=Gv0GHi{i^Emv93BDp!)k>+*jD%qHML;-iq4c3i2U$ zOYkCFm#}=|AUMv+uM25l8^ThNWv#A^0nj(oQKG37+tC<`ehX3ER!5>Ebq`Nw(-int z(D-QMW9{Mz+~y5!W;vrMT$*clG>z2l5Cydc`p_Ob(c-}YtmD>;j((QjTqOfTGk)89pW)G0M>j=cyH1#o{f zHn@2rB45I1k0F%xokm6?18w0uA*z=(9Hlt9 zudHJPoxPH**G3i9mRXWZATMZGF*0a@@ALiq~-*D92>nu!McQLa|35EA%*ZJ#3 z1p8M>%dMGsgYEAg-|N6INtD0a_f{uOP6%Y`b}XDqeBAiP)u&qw!JBLROqF>G(rCl7 zFfCG7FmRBNtA9cc0-sh~jdQ51N@~&Lpeh|SlHd8xUtXHy1u+H2s0Q;vQMHku|J&gT zzOWiwjMx3cboH&pHKdjCQ!!UNmAqbURYeM8lv}d@~+0HtR4ptQIQr^cY zN9y18O|x+khMhPec*cSbjkRHbG9D9#%x)SdwEn3??4T~?55;TT&`0x>4K&FZ@0xlt zy$%v^Izzy-)&t@rz%EvV>hM!B0^J0eRrQy>nk&0%2yRt%6yEfhXD%RB`6GmlJpjQn z3KdM7lT-Vzo;5NP=R%8$CfxILo!V|ib>f61d9HtoCLE?tUIVr_y;S8mU%-4QzyytO19t2C|PdiC7^X*5rj2Y`YbD1sv!58ng*90|{GTcyERXWrj zy4Ws5f%)XX{UJl!R^Uk&`+y8%53BVIA9xjO4`>6m0S6%2b0rt19X#88D#%`*Mrc*e@N; zK4*a7&D}3xs@_Dn@3F`GqkNv3Hg^Bi0zFcUt<}8+j<(Z!(M}IXEcvO#q3F)_()|~H zJds{9am~g7scTfo6|*1ue9vs6!b3>cXF)RA>D=qkW?*par142^RX8`Iu2O}qW<=R^ zwy55>^4;C zmV?S#NR56J(phuRM?(LpOgzg_(jDVvA{Z-uHGw|sqZ9{uGz59{PPJ^Y>hJ6|ksHZn z1IYT&mxrlrb%dZx3_&@o+mPN2MyS!Lszn%u`{=_>r;lKb$5XQaaOs?>`s(R1X5(rI zs1r3;=&TgIVySO9O0xGQ+u!_1cH)(tW+K5x+pqsQYkOL4HKj!V_UnPX-!Er$QC>vF z`w#C_Wkj1?Fi$ zC)Q1Ml!?rAArJ$k1mdtXn>*0;E=?S8-?P z-(`^C=oz{WLgr2Qk_A>*} zVl!Upc;a#8C>uuZVS+~x8ACh5zB-M$m4+*+)ZAcjh&^0$C!>RCkJEFf!VZgN$?I=0W{|efk zf^oQA;4Dm_nh4d}_qUchL>Aii>vGbp--el>o=4pj2tQ(OU3K0;!xBmC3}VG2HX49Q zWXL+z(nBIr4!NJw;)bmw6yPekkS81&!jtr}>%)#dEhpr_j5O4^KR9Y`S8v1YB%eXF z=K3S89icOABu{d*g&?UX^xxO-g|+;w)Ia;e6BxGkPxWC0T$=a;V>Q3dmefW3KS`59 zL1V}$;nS{k)IyqWP*B3<1{JaRm8A_#+sqE0MEY#S6?wpEtI^)?R&G#;)a_z@l%Hn; znA*l^@-Hh1?s2A;pVeeJW|p5btz95*casXZBQkEC2Kol{+43;8@||w1A~BooGBeXe z9e*$AzWizVlB~A`ELv+Dh5c<%OTJ=Po4@;AAu6z37P0T;38Rbea^Y4(eD=JF6=RU} z%9Y~#91sRe*?nM~%uP^)CU`}|g(%6bT56vD6l6nHxX9-lHk8X2`q0s>ihS|u*_IS# z`-f-Flel9Cx&y21ux8>u_AYQmU$+7ZY;ifHBJxlOjq7REY%w9QFgJ;%-G0)lE5mTp zb8*y*Lo$n47(MnEG8PcPpn+-EA#-qPYK)BD;A3~#a2HfPak-Nwn<$LMgbWD&BE&tK zQHD}Mrfx$t*^OmU2O5oKwEi^XVpOx_oY{bb8mDgOk3HYt-SDsUuEwZdW0v?#8_5Y& zTU~1wb4P{uOBDw*>!N3aMComF0fPrJKINB~mO#C7?!OW88u@3by7=|Yl+hnR@BlEu z^;MO1lI=+_ENKd8Wqyp;8^zgnsA+KtB^1)_&KO%~neJn&OrNaP_xohl`Vqdc$=^ZL z1fz|PweJdHCWsEq(SkI^t>r-27OmS#f9Q%e=C2P;*9N)cghJcqFSz2uO~&wmm?%%> zv`_k)1CW||!*Rg#Xy@0{+NK*|{u^P+U;Xf)m4DjR_B`Gx5}HZ`X+P~G$dkkRa;@z>35v)5xJQ&Sidr?)-#Z!UoqwOmA%qD)$>)Vj$& zniWXxnogV|JPI*inMFo~6xE99{VLun>ZCEIuD)o=PN#4`V)cSsHXP(!EeU3}iCg-g z4MWy;Xr1A7ibfwA<4?Wzfr^Ny!q`wts?mh`DjUzXasbcXO1^*U`)||WMPAf_nCeyp zt8HAUJLh?&vfzi`A+qAL$R9_Jh!buxQHFwXY^8ro-y&Un8L;6Y6VB_k9Q-RNt;?)4Zc1^jIMsww)9=ev~dxL#n-VlnHh*l z+{~eNeXB?p1^Ne^wjXX7X-wzT{?gv0{CBMCKaFJn6lLS_nxO^>IW7*t{CRMTv$5cD z3=;I{ph&vV_(2+A>Src;DnUkypq=d88_zpU-r`m;+#G6r9Q7q(1a}J7&Gm8LC?d}Z z-|KoGmf|UzkEu_jx2kSWx@Lg9X-zb*b_{zs;Gs!BwctEd^}kQ0})@ zo**nTLaIVZQ_lUpD=!bJ24{I>eLi`Z2PPrzA9N^JdC{E6J0ZhslpP}daLi3}n06X= z=h=#1--y$Xs5(hY;a?l4)^dSH!vrJEV?11%bMN5Cr^hbI;CXQq8BPsn1qhOo;eGU? z`DKE}+J+K5DsDNMn(gUIr&~?9;4mjzK|+Q=aEglHo~Ovd38#lsXKn4Wxxvr^`p!Jc zpxqw|$VR$)W%5`z^|MqU6=mdc^Gx%1clV(Izu7;Y&tr!h^3d0ZTOWeYQ#Mf6T)#c4=Eh@KR2jAD6evzMd zR)`S0t^GToZ&`tVR|`3<_G3clLD|~(G+C%2vQgNB{6Q^VwZ;yFG2|~3-xgGhchOB? z9AR`21n(>$AyhbG+EosSXo^O%BYrClh9#i5N2(*wwoKWd;RY~PyjZQlLbK~zUaxJ^ z@T7qi;^LnC6BS)H^YI$U&d4>Guwo6$U}q458q~i(^guQT&}O=XbOK_F{_Gi=y*jt+ zNsd%|ec$|8pk<%`f+YL3K481MGE$z*G*T4LHrSd}Djj9- zVSX{|u-aS7A#t(kY#*LYc$aQGB}2u>ApcwX9qltyW}U+%&KQnXP78rn%YkfnOxDPk;;2g`K7cdF5$`_Lrwd+U``D${+3^IH$d zdE_`;B;CIF&$OA6{REAn6|w!;#B2T3#1Xw_DZ`ZU-*caCp(saW{#{`|2 zfZ_AT39$nSJ80(EK$vG_c9swi7hYRC_(?*Ee8A;JW>O~V>&DTFo=aAH`EY>+J`h?B z=iq6Pbwb5jR`1)o8pn2uva*DAb-6R*519B#}K@OSNV^`)6|M`vGCdotMwl*5TQ*g2wd)G(kWpTFF(z>Y>J$Z z5Jk%}#22-%HK5-H2<#Quw@6YY{>30K0thin>W!I#;(xI4Uy~BMy=}AR6IxMjSu2_?4@=Yu0S!=IM{s z7Z@*1*x=&mr&~h|#SuGP$+D1oT2@#1t?bxqeMSKa8m6x98A*G6TA<>A6IqV@*zn~p z`ndCh(96GNG>M?k&k(fZtwWA;MEepOS1VngS*p_Eqr8l$w2~fzR5ipsBBLSwJ+_X~ zH!mvi`FzdU(*wbOP@DTxL#FV%339igkW%7C9guZp!<|F%rDe$dsM~Yhk z31)905KP&LAf>-GUC(YnJ_i&onqSke`5H=^h3XJR*6hP(eUWChBtxQW(-|L+Ens>@ zJ=#$10K}@RHDLP1v9MawR?=s9thU0_AC-|oWPBJjcZ_r+m4GDfT+74KPt?{))kl-C zJThS_lOj4E=&*aJAD^1B3*jRtBx4xH?pa9^K*QiGUPtiTt|9TJH7O&qBHrtJFnbp4B{JSYce| zZ{VC<*a`RSeud|a4)NJ~?D+qLO#Z2dcC+0WbBnGmJfX&cjvC_C*JTKVY_G=yugV6T zP$d<}j-{9zi*E9X!laVdI|7lDM|n)|O~hu+wUOm>dyKmee)6moj9>E-5h91NMD%K$ z*)1`(jr3%#)Xe|02y3Ok)s@3AwkKl@?NOz+ZCuaQ^fJ*lyHNPtVS$TN-1lg;s^$YV z<2OC0dpJ6}F@f=N`86=vNXB~dvj=bfmHX`r*;a%wjRx@PUs6k)D4<(GyeQ)<<$uR> zMxO9v?q+dSd1Y!7uVo2^_exhhxH%NKZZ^Os1RJPVHXf!sdr!&U2tR2j6vzdl>$M|Q ztjup5lb0Q(!Z}PmzfIX}a(w?sin2SxZm&iIN5^>F?lKWI>p~x+FZs9XQ!EyDEd{zu zkwIdpD_erU_r*RP1WN;Z9BlgQXb4u%vrVzp#FdYwpqwKbj33`jbEqc#ES^JN9!To} z>oBnyG|9VxAvmU5+wqbh?h`=jt2uPvYZ|@qk9?o4Xw|U1#eIjtS%AY@FdvH6G&EzbGbeKo}6161436`mUOt&|FR4!3`N127<`0P)0!`5Nx!v_}-tZDGns&!9KZW{z^Qr2X_N$Pk? zpu2D@rpx~0WAi>g&|qH+);bp9*=i_3w1T}{12fPlrSx>!o+9wyqE4#!IEl6UYTBcU zsp}4vM`_yjzgSkp--bFl5JEUOPtk-5DN^0usvNK-M`qj!TIbKpvR!PoEG{*7X&6zC zo`ivhtR9mUgZ2@6v$*L(2E<7IgLSg@2nc-6EC6g)nX$?YgW7YngL#|+@t5<$BR>EvLn90g}&Z4-A zwX!Tw;S6URFhB3;FviN9zaKR=`2H-y#Tyr>n*+F!sz;P9;djXOC&Ux^2V}Z=bZSBQ z0ombEIO$`(@_o)+8z;b$1U=?BBZFI2mAvM!+!@&0`t`+myZe^Uz2c0^l37zsnuwsVHY ziP?bI%0VU+4TvqLCRu?EF4BJ-i`@RpiLEUObAM$tC}8{k;#M11sKf_tEuE{XclgUk z8)Yk!OHivoo2`Ljc0eZksP7yEby_utG@dr^g9MK6YPTHut67(^>bRz;#0~~0>z&o- z|7BwMu3ax>K<`jM~7!kTH`5&%3<%Ad_=AP#qq znV}t?<2S>x6ra=><%W5pUmW5NIy}92AQh01WQ1BZ&*0aT3K;%|Hb+($4DV|jr;ShW zH8TreWWsOnU?0{D_1&-JJ!@2j;BYKi z=wLzwF;_XfuBjBmV4#8HE=>lC-0r!HEdvH^+O zV*qzQatnb@yh{-gt_FOH>|*DQ>%P~coEqMQY8&>unH4IEfecdVZ5w*5sTksy_e67@ z(+K{ln4_G8t60Icz`gC-Gqm`h@>o{9QY+t6b{q?09E$Eh<$mR2#HDBy0<{DV{gQ0* zYgEcKCmMwQ7U7M4`AyjP@5asCKqt=x!p~{V+VU(f9QXM1%TKDa!^|w)uPH+R4OjCggb<9>Hz?0{fBT9^jH0MY_XZfhf3Gx%#wiTr)+dH=;9@w>E6KvCQtOwhyNgz zW*AzvkFy)4f7caaHeF4YxUvTSv6P<57-c=BPkXlo zk?-Ux#^e+?{Y0@P-|do*K`ysR*82A1&aqa-uc>QtISl) zg|qWtyTU%aCRudDk|3T^GS;ognf>-ah1b}HeV$m4AT98AXZxZ%y1F+kOaN4D`p`Zx z3d(h(V6572*}R<*eTo(?C+R*s{oxKIMCYic%eWECy|tO+e5`5hdA{hlq?+^NU##R9 z0+4mQdYlWG|(}rFr*pkBqRaR$10~{&vSavX&N+K0mwoyg!M#EQ%pmB4-Jh^h7;q0ZcPCpPaK> z&F4Z&sT^<5j!zdAm-E*8-Q0hUZ*!hzge0B-2LOhraTQ&K*a-rBCemi#=vpWhCJ<_ZBH17 z3hSAK70sBf!EXM~RhGk}9<{3FKhu$bsZx7hKI4wj205FPq&mS(yW7?OgA2kiPkZ|n z`k3EPB$2qCJcO39RM*F! zZT;t`FkE*9zTp0X)X2Wy-+`vr0+@`7J#FUb|iTn=>fCru6itg-AwBMsg!6mgc6h8+Op$VtM4=Iz!CQK! z&rN1a&n?*6`YI^ngQqxZM|nl5zP_Gz&gJlO=7uU<1Y16&nfs>F((|}mXo9(q`(N~; zp7Ofg=ct~LX2U(Q$GHH7l4Xj1JKmYt)6*3Dwh?v(2)Y$uSh$i*7X7!G=#ll9ysX!N|IHC9YG5Z6BX8*EwOert8MsTX zI?Q$9tN1?tG)l?7zrbX z(kOXGnykm zYgnH9Yy@SeK{O=OdS%F@YIA*`N27z5c|c3Ff9m4&>-uh~A=aTmz|M;2Xe)7mz1pIY zsW358oTRdkEnQS|%U-d{MW7;@Gj;I=<3f^D;f2|-s^H*H|A*JPe#bh0m*;qWucGs; zf~`d9vH&reyIN(;l9NZFjp@T={lcr3zqaU->qy}t9_2hx?5(=%ksfwkcCkvxjsi>V zpr%}ToHU;;yMzA=ho*Q>5UB%Vi$wA6ei&N@Ju}?vCPq`Yy^Lb2Fh#t`OHqmIwU7JWlF{onF%BXJ*`&} z`yeGl@U<$+bDtg>UmuA+4fNsV*w{_{)DaP0K!+MinIIVH=mfVrG

7{;e7ndk)9G5S(-1eN}7EC=%j4cTP2X{Q;REHGRNjM|Akq z%ShrhYd%sEVn@|a`Xy#q@Q*_8!(q+SWXLkgu3j6#<%WN}ic))&i){T>s42DYKJ!9v zkl=}pV!#7Bt3P(BMya@F?u!TWEPz1U?q=kOJWlLe_6Nxdwipk-v^`lIorZPXW^X%>wRR|aCbw!tvY)K^m%8K#Cyq+ODLeLGiR+SwoU*FJi8RPq44 z&Wgl7%iZsyn0oQ|15dAzorwo)!+IS@Ik5vJPU5KPf;-LEI+d1RyR8C9qaJ|lzo=V2lLeld+CC^}{Q7ZL|Bn(-5^7O)q{n8u0bgCd)-GwdyBD+<;3^#CG3=SyM zdEq_YhJLw$o|Iz}&O)xLkW?X36FUfkszGe*I!m6cq9fDOlL#d+j}&m&mBCJNONdoB zxJ6_@fVQoJeeDU-W68*hr`O-kedHsB_uwQRdXXba`;1V@7ixz~G)@=g?nijNNnlChf+QCXY&RBdFke_I> z+=5Go&O`5g2RAfS+c`oY$j*ztT)fZNb@Pyg=e@l*>1%6}e_Xy&jUmKzuR@?6F`+uEQ*@>Zl}y z-&9;}!cgR&%#-dWk4|hoo7zC>a)!Si4*6f)ee-*yLDO!Mjcs#cd*kfJPByk}TN~Tj zcw=oQJK5N_ZQC}^yx(`;^GBSY=enk=tE#K+>aORmZyPUTIJZ0owr$F{3&c)9H56V= z6IG%etz)0V5e}b>Wo=Z{Z%`4aMZ31uq*6Ossd`Wca#)IMnX)tk8aGY|bqV4@#*}b> z9e=r^HjH8v)w%mSFVj{LhZ@NqqQF;C(y3_~r zCVfe_$nfyggqo+4K`K zZe79I+o& z%syEzw%7FOTs-Vn`%y+Pm?^uQN~Ui7L;3v8N8CFhty`{21}1E`C;U8O#5y@GY1TD8 zEYrhy_xX4>W%gS2 z`xAumTUH2ui}w!+o?w%invnnZ)n0f({{25#QsO;w-tj^=PV{=qQ4kwnlwW3+$qaAz zPQTT;5+C`pK_LNo&jmGP+nJ)Ecq>uE2O0!0X~xLnCP_MtX1ND$RGT#Cl{>GhWy|O&5CV$oCcid3~w|QI0 z*|Iet3n=An^s({w@Pj4+H8p=;+%Ms$NeTD%5z68;($3Q5X%v)vsAR8cqey>Qy;-8e zEp{M)qXQSZ&X_O*;jHW3FEq-9Ngj(UhN6{iX}gMKxg$fDeVHooN4K;i{ZrLFl!$SJ zA-fR4!Wt;FMU&3uf3Z<*Au?n$Vq)N-W0?>B+=`crofiKm&yfk{em36u^=$FX!O5OU zkm88BD~@HBRQ{8k0oDl;TinBJ(_6Q5KwLK4RzuA*VB5Gq*|meP{r^}`TTF@l(-$5gE0XV znNr{Ho>z9l1E0?3S0{dHGS1Br1!l3naz*)G_mOY>e-^yiPT`RYs zZm`5~LZ@k4K)qb>o}ttA@W|VS>*m!A^UY1}oM|VJ@x^wd)wKU2s$>CX5l?ZeI1=1(Mqa~GvmyDbm7e1gNhAj>(csC|s zD&uQG9E~PSD=wz)2W6YhK)H-w-T8Tw%F7(?vUE=jCHoK3kDky3J!kdAI8te1J$Nh) z;%}TaIzEd}zBYbfCfW3JTZ{HIJv>zQ3JGd!Yf*b&qm4om7wS_TnU;1w(>|pif-j4; zREKNtwaIrZ5*ccD(1u0{J#fI>>zBc6m6KrGaf&HW6NhqU45POp8@HAfYW0i_$dv-L z4<2D@EGX1p?{WAbE}pDljTXC}$AiCI*+`xKH2miq&~WOOX)iUT3(;?rh$qTK(PBFkypTyxo1c%e6 z?o`^6lS6y;$EU8@e@>{zVeQmRh(Y}!?BC$J)~@^e2=f&sqxzu9eUH-Jw3EsU%tqK{ zME?Th;N$`;=F?d1d5~^gU zWg(^ zbCPP{_C71bBaGqHifaU>UEWOn5@DbUkTI8_G7)t7yt%h;HwsZjrMg;(RsO7?1tiGH zRGe6{sUVH|eS9Ijk^j}=vdRwUVW}Ry25PDe{whLon)QZ<$|x3??nnVTmt-ku4LIQb zvZpl*Dv$LfW_M;hwBhi8Im??ORCu!+=(z`X8<8L>q<=RWZoB>lbZ*V-VUMkvFw9{3 z8Yz1tU`+qK_b&I9gbtEY?*syhvCN=jOnRWK%H{s~v@}+?=JMBA>%o|pDO{hIN7ws` zejiH=<2aW_3y;~ZuV%jFUZw5d>V6kiDwdd}?9x_`m3=s@qz4MwAYI6^n#l**Sbe2W zk#bD2ge25nib_ChLVvhm!%4`39Wr^o1C$w7)c)i8O`}87C*eaG@Toco6q6i^CjpEa z#N5n%TsaVOdqkDCq=DQye0n$tldCiH%Tj}(7}SavYg_cyG6{YDr*Zc3FO#VNc!PeV zrKe4SW*bD2K^flYk>Q|&i?$Bk^2?4SRaJUU16oWn|wFQ7bEOfz=rsvg%I8- ze?2>~RIr8ys~1Px<19pfgu442!8-Wq8~9|wE`k`EyajMIX>vQ7X8go52EzL0@SBe( z2U?CZxce!$JCZFf${kt)H2uE-gy|Kf&5Q{)nwdNR#4Xkvg$la4WL~;Am7(t^6lY zwF1A!heDvaa&Wev9goZu}GkmfwX*XQg%oEMy8*$ zAc2yX>^d{EzTukmVhTg3b)sK7x{#ra@ImR&1h?LAr-R}_}V%1~N9 zKWy<>m^NGb&t_*MGj5D8le1};Jw~8@t#n-Yd(LpY`4TrpK&8;jIM_r_`HFN~=YH!B(bs zWxGnvyJEfs70}JPDG(GgMoX!y6DJL3X?JiP%}H02Ge~dgB5N!a*PaD}&+6go@$D5N zbPLu|ZPQE;#o!yBez=y%8Bk;4QBg-)zCLL+^J>L9gCxTw36jIZ^sh-b)ZqiUQfH9) zvR3fZ+Ro*9I_LTJuqX3!Q}e$KCuC?BjHlW5MIOQyC%BHdfvwt%NI{+Gwunc)`B0VS3{19l)vynOrr!$gEq*6!%zPBpfzg}c3-n_ zT|wLD35j$@C=@j&$l9jl-WWz|@c!712XAgC-FHNH3<965+K?8v1=1xX8($eOY>xqF|QtsX;`=I1AyCP zY3JBnU!z`(R(JKX<*|NTm;dz3;CC=<5hOVT^w00+7+~|M6nHvQA3gv!f6EO$x%M+r zdDJDXKAT=`jBRJ9dY$R0D{I$kp}fYr3G2@|(+9Nn;RKm#@fFauCPYv^P6oQ)J|u?* z#RP#lilF}IpQSLRS%GF(JF;Qm^h$NW!kVM6mw7iYxLIlYttvIF565)Rqhob5-*uk5 zGS%zLpwU?kdJ!H`8zH-oT%GSQs?A0CN964jKhL6bPIPpa5vz1~lDUG=3Zc@+YEIbY zr==7m@BdxuKbwG{NpyEMuNaU;Z9zsQp-~&&8Hwg{;k>_ua|QZIrxaV_@GVE;%{svv z{QjQPGhEJ!Fr4jzK4}b%MVT(nOzQxb*U}Nb2ZMd2TY{5|&NHL6)$v{F%p2awciOT?^v%Q5-H<p(Yo8{!>rzojkQX~{vv>e)Vv zo`3JchRP-jTx0Ch_w?2SW(Fkqw#i|$vX$&$GAgSx6DssIQkh$uOGmZ)?T&uBHuW)V zyZm>%rRWfpi`cP05YXB3yDp^2Q0OWjl{;4jShwyC2LJxC3SgvJuws+clRZNl+^vzo z0v*;EKApDHETF3Y*E#7TA@G}Fwu5`Vclm(hjMvG;&%t-MxXC~)xmM$Bl!%~MD~=8U z%$RqU^k5Hr+PYJ{xDSEet$tDib zdygWG)xS{Skd4CjhP#E^i$n@V@mger{<;r((G~8CVZArm`)Lc-$L|cV2zL)C(i#%b z4T5jyI@903RU$oImi6OwGrf6<=n7)TR7cZL1_qvA=6}xp@hQkVAxHPQDdkVXBi(g7 z|7xHa&Y3)ykhJ4aJaX_J0Ak`0uc>TZJBMW@ozpTd>cjukyX7H(W5)vffEDl{$5|`HLB19Y)fE_*Xv7MC>*j)Iw^Anm2lU%Yo z8!uqU`Ud%HCVmf1kAtA7E~&DJAf?pk7-F3dDk=_->!QL zEOG|~(r|yEl7ds7>ASr`C}#Y?*D#YL$M19;SOxsWl~0R~WMk~ZhVUwOm{=&!Ahc>R zs&9;?+c!s9H5LgY%^%&jF`kAVsaNDo=;fGDIOcmjT$*WX^{8qoXIu@t+m0XQjtc9B zh=OEpzY!Or?8wjWl6Ef}8yW)cOFi+8v07GAHMelguEfh;Il-&=S7KE+Pw9(G`B1LHNOSqsBi^Svnmwpp*>2SpO>oq zH2cM;3W=HMbz;(oIO@^PU45)wdY!x- zbrRZ~kRF)}=+l;)#Kc~|)Bf1;;^cS(9$71N9HzU+q_57fahVW6?jF;#EJwCeiLYFk zC4=mAWpx(x-J2Fw5?5k^O^e7%qi zFQrUBj7?1NJ#T3=?D*GG!K>PSCjCibT}vW8XQM5`0R!Il1}X z^lI&8m(Jt_4 z^>eNhcp)&4&s{LrAxq33wj(vs%5@^*d27wh9?+AYu|=ybtw{dU-{EtH#MU=FDr^!> zoL9sN$()OqRHi!|O(V}Cll^sm-HQ@YdR`Jjk8yN%caE^xi|QxZtyJJvb;UCcYYX8` zkE<1&C|tv#dg_WO+qi`N;vQzKxMDd@|Gr3PpdYZ-NthE-OhfrJd@>O?9#CCRa-4)u zFfXw(g%sdFAFrNZ*@5U{O^*J0P;I)V;>Sm1V^b_bN@%`Byl~HU>HplY=qW5+Eo!fnLS6p-3FdYt5;5)S)&T=gC>ww`PfMu0i_tJL< z$^Z0~={6FGG(r=aLa4!A96>4Vh){y8Etam#AF5{dNuMf+byA4Z3yN%Y>)KFmUDVsy zhi)qf{&_bST4J(VA&^x0<1t$l=C`Y8-3Z~zRE{`H4QukA-mGQy(!FKY9{9S70s=#P zY}-nbS-Of;sGi z(v<&Hj?4Sm&M*VDUR`Kr4r+AZVHi3<)KQ9ZgrtL8iAOcs&aXH6vxtA7qE)3K0FghI z=(VUAV%HjA9+92lP7Iykf*Z+0*rjO7UXMIl4UMv@h|py>F1)rXVBTN9zM+_8o@ntY zLOtvi-;zQECt2}3ub6qCW`MG;c&?JstxDJ z;;8h=PCi^b{>@!T;oB&0=X3k5c?yT!jO$=m9BTe3SgW5I$)7X0oGR_~-nuc$f9Wq= zzSF6(>A`8}QpIyz2HrMT< z(7cp)k_QBUuWtJ%cIM=pdQeeiGzu>Lx|-kjLT8#9j6B00L93#NeOpE=7vINQ4Rtzv zRSx}lOA{c((T|sD>smC@`-kiU54IhjU+-QksEZnfmMPs%&_xBljkpacdy~xSnTey) zCZLrzPbB|+{G?1FTN-SXGJfQU0ZF0dNk*yKw>R`WuhBVMe_ES1b~G0*20PW7fyHom z*Y#W-?v$$3OW%x3#`*mx*xk#5rTES-@)icFOsFF~W{~w|t4-;Pd97v@FS-bo=j7~x zj`e9q8feSeab}R!8P1mGP}1Bb%0lqIdHk7ZvRKM>)(sl6w0VZ<%u7h{Ifz8m*R7bu zUfq|-hAC>Lfn+2q2+ixq&CCZ+?6cW^1Rs)EP$9h0=jyje=D|yfkEO&h3MW88VZv&0 zY#IWK5`g}x=IKWEYIYpH961v#!MCG233Sl-kiE9kr*xoxugml~K{6Qwl5G7h{u)^g z=(ovhrM!acHab@>*7bR)HE=@w51+8$ez$@sol7ovy;yZ7e4Sq{*)gWUTskEJw=kuj zOy~4&!=Jtab@EJ^@6Q9{WY^<^|6cR5m$h)_OH4Cz8Wm|1|Kw+9otC!JMQ1Voxb4@? zus2*i$8M`n0-K1Q*kk1|CmbHofZtqTd9aC7?&ue^?`^o0-Cfuwb6vqIFi*N#ZvsSTk2kG-aWaGY-zvI`Bfn0_z`pjT{dyZ``V) z3;)Wuz0WU}#s12l2+=%6NQ4KhVC}|7DoBw9p?injqQW!TxaB5PW=2Zc?mtX*;LJ+C zm0zvMw)Ut{^4ugOd?T~6dXgfRtawy%vF67Ps7D$+>wKQ*sVUlv{%{}$4;m1Juc5*s zO(5R5y~r)1RRI8t`j5>G)kro_a+5H2k{RbYV0Rl6ecx@dCS zr`e`GWyhTZ#p3tnTj*3;$2An#3vW^lGL*CZR>AeJ>~8haUfU-GMUF~`-Br)f6O!nB zAXw48w21~Z(&1{HiG+h>LKHEnD5uqGMBOJqGzxRVUztiE-D*T}HN}ip}Wu=@1*N?67G;L|iA2nDrqS1?t)`&4w%YZ=gNy0i9{>w{!p+%u9w=H0RX zw1lV{8XMji>1zH5jj5#Y23m^U-4bO$3X)X%=oE@h z#eR0W`K}FJ-6g4tAxqZK{An%eu=nYAubH>P|DuoWb2@^s zcaxf`)WhgTfKu9gBNFBz@88tPn*PSe#5IbP!5kK8$dcgsm62vxYVzqD ziTA5*zn(7hB31s!4&J(bSwQUHPU2$lRdpMt5E;VGwbi(;D(h;dk~UpRCO9+-ue?N##WCBcMN;dq%s7GXad7QJsXFaXnd#EB}idR~=``NczQ z<7sGRKY_q6-`4!3mvzH$cftz$sm}68Nd$#Vd%0C9RKCLoP^l&3+Z&(;L=tQ*{Zfz7 zpVU%YvXcN{l3owYjeh3GnP{k~qKow9U5xPrM+&%^jPLO60(o>R-6NrxQn# zo3K8#0V221P2CNytIb^W#NbOQNdr< z1Wu_nouv+Z+ya@IOB5vPaXq#Pk_neya=RinSuspGjO1Xvq@?9P-{+E=+9FwVp^fY^ zBL4F+{fQ`k9XC|0ET1mrX^uPF>jXR_c4|1H9P3XsOeJ0n5o2;P!nKzCb6xcGelnVFy%CFOvl-QFRj1gOI{=VvW0MoX=v?dPy!{aD-$R*&wy|0@7 zKuZW%B`I(3MTR6+j)03;p+cIWQvl0g4YtFDV&_DggO$#8C);uK*1QUoT@s~!ZWu>= zUh`WDktOO;j;8(K43EPz7Lh%td1~>>l6FN6+~CMQQcjuxYeLWuz{4N?R_R>FMFJ^w zk>a=a)JAZ|q+gK{pJcSULB|W4VU*v}P<6`m- zWV^T)H!5z+T(`CMC#AJKUzasF8PhKm3aQQZ_;8jjvZqqHv0oSLP5Y;g2~wkAc5*1u zhd6Z1M-KJd}x5ksp;1+arCHs-c-z$OUz3Hx5cJ1x#{0Vl$yw}8Gnf{ zWASxM5{KRFeLT5pN!TP1N}HoEksC`t2~BozCnqNummOYzilc)_ya!;BoU7G#L2e}ShMkZ3hPeVC zCvK7jH82FtNtR^#TQ|>=xGU2AX`SX@)j@8mvw9L|@M$M_XZgC-vwE#%lbtaMeJ`48 z@7e{3Ab?}EMN46!5z})XeHveRa-V8SKv#Iy3!n5}B~}{K6g~B^S7nBJ%BQX@Ntzq8 zIC?=9&#h-Q*N@s~HCeAVf<%EWXJ*cW31%B}i;ev9DNZzlv+C0?@#n|B;e9jJMTd`t z#nvp~Q_<{K`*Fz@o!wDz9LVgxt!;@?kHuV1G^kje1xH-ln!>oz@|*Ju7%TrIVr6FK zrjPRa&wG5OFfjlOiS89SK3_!j825k3ML-A+8r<;*-t5Q6LZRM#bPDer@Fy3V5eAvq-MhT#0KND+S_H=PkC!`nyOT{llX} zDBo_cavcK4$4RQYyS<_CP^FHL_R+YMZ@4mml!^)+UIw5MVVA0t&n`OPzn5R^{Sdr0 z|D4-O7`}?K<>l>Q0;*jnZBeD_Fr6~llI7gwWMz!^=e8x{{H8}r(VNMGr77yp7nZb+bU0te50D)TeBn~3LBbcUFaZ4d>;r=0psU!`cwMru+8 zza;oXCTX<&ghm%BE=Pw$0>ER9^(hkuos=k{eMPWbQj-xisO(;C6Pc(-4lYT#2&}hhM^xH9s zqqE-vK|r7h>|UxATRn`OH!!AgQP7 zU_S;lv=i)npPeQ#PwVMw{q3BU+K6VV9mZVi97(Q1)x@EvF(%D|!Rhh#1I;=_7(7Ec zI#$x*Df4+&qS4bTfsmre3(Aaf%gFzF@z9xC-t`_;=0{wPl7IUmgypDA*WZz$ep&YF z?QoY93y)Q%q7Te_@N6m%&L8=Zbj5z$QUgT zEMB%>v$h_32INl<;Rt>>daytb(qJ@Q$faK-rh_=;(A#H9o1xWPLD0lb)|m)L(Grx+ zTCCjI=3f)?RM^oTL;+txW9u;EcrxD`je<&;M%PYNr8M>~!6}~pMv`&YyuU?*W-{l9 zqFxHUbDHv>sw7$~-COUozuw1Bf5uXN1XY{}vxqupRgwY*ZEpkmS-sa%!Sfx=^deLar$tR8!VKDuoRNUW|Vl>{E$8y_l5r(=;Dn>Y+4;hhjF z*p4KF6AA}dq3d0(Zr@!PAQc9RnsDEr$};h{f6@A%?P)4T?>>bk=16~UFe%<4hCi$A z>fpAW^P_bcrr`vmCdu%NH_~uR$ejTt;tOTM!SQyN;j?Q3vYnPX9G`>k7?=c4@dQHh zUVf-Wd2y>$KILkoEJk0R>&gK0hks7t9#A@>4SM3-IYz=SJsGcB8;M~k;(1N&WJE~Y z6#!{PDso*Mq!(i3x4&BK#{1ygP^`O-fpzpq6@9kS-RYq~ta2u*-ZL!*nV(NkP4e|{%<{|1B1jXmATjgCDih@3Cw z`-}-CUIm8%wh93PAd02lXo+OmF$*|qub@~oaf*@h=ZkE%O$$WO!($?x^uL)0TtwJx^HsayrdiYd9E z%6VvgMo@H<&2+{SpH>!C^Edyik!Y<{cyKU#MWCCn=kPiEj<(O2e*QWrFsN`GP`De> zd7Mv*66vrxbOE!~J`U}W6NOH&%*+PHydFkSJD1}DxD&iVKM9pq05sW&+ zqrkPEPQexp$jcFFa^q=WfOQ%dvF)9F_DlPnZ&`;ZG)CFOns&3Cd-WJsvYZX7S3hlQ z$}yXZe(l!;V}cG}NH0TJs6HvrF?$$piF-*N~~&*j2I5dp}(bIh%W1K9%kM{F+F zGj;5_N?q(Q&{}IkRAXA5-F#snzbqtH3+EFqys~4QdUM-}?1CP|atyn@l~gVniPutj z=RGUBqT~1n+J=gl3j6RUdP(MoVd@dv%Ciz&QPN-$aJ53Ntk=i1D62nA=zKUmaZ(n$ zmii4iiqfH%J3Qqk=p!h)sCc3d_;oN6A2H1p_`hE6;=3k{5mn%v>^;>1J8m1LzCSu% zgU1Ux_^slLqMR*!MmvgGivpAueQ4_8GJm^kM! znAEE>_)v~ejV=Eh7fte^RxS&C(HSdN*8F!Z{{A1+lW@gfq{weTlU-?+?g*(5M^AvH zM$+E|EUGe0_)PAEY^p-q?kreSP=5+>~lO ziYR!NIQs=BjNn**rlpy6>Faoj^aQd{kqvm2;wzRqbt*pWe|}~EE)YSr9@dY7v~8Bj z&QdMfyg}6@91SB6_5#2P9lTBnfjiDB6mX4+JA5-|T54NDjC%hAN@?JF=GbX);0rxv z2A=-n9UTI}9p=$NM`G4Nt=Fh3lvw{j;cRKM3cHKFk=W(I5K8kA&>O50{ov?g& zO>}*9G9E1YtlP*}sAa((!&{57 zUf?EV*C_^%ACAhbMX>atf!hIS8JMPGtBQsWHRu7YB2Cbo zLl?}di6)Oa{M182w_^F*zK7o-D`t9oqv8C5t&swzl>y)8fY#kr_e6)t6hA%&Z-N5) zpR<1JwDRSI^g}ZPI$LZ3--QSZHIF#D^PK;>z7``Gsy{4TjFa2#p~_m;Cc&UR^x95@ zy1};bCww2%4}r?qVjh+mVy{XmMful)z%b@##b-Qoy};7Hd?S3t8mFpZ$$*?cMVg?ff& z)CsvygNlkcOSF1ipXw2{3H}*Ye~o%_j3*q(ZwJ%3&E`FR#(cPtW@jT6zQGAwNJ3~_ z)a#AZgxo%X`gJP&89M7an6v+&9~537a7j9N1YYI&F+Z1E2S)5KVS?J(vxb3XEr9a=!*2&ikDkJ`j%4#<6QcElRRURa8aCeeIFISLInqiTnfnkweedWLwrvc)2d%CbOE;QtL~x(+(rm z0%ArYLf;gP6|j>;~-Jt+u)Dk`~WHpPWdV&2O8%+q;i{B!TEu>uL78 za4v+oJT>|^oeyQb!o-mR|564EDRX2bNgzp%f{j=&rS86)I=KzLO!YXGyIlpi;9Lq` zPL{NbArH1}nnh@3bQ+k<_W%t=u~W?Is2x|uM(k%7MJ3nM5=ld|kjDGFBdtDbSi0Ss zrlkE*ctCW^^PH>G^H5-Tj19g#bg}=K%B>u5W%Zma`Va~+I|0)Z3BVJ_RhjELd1%1H z+AFj0&Qc^&qJjY#WlKeNqK729a^X2ibqZf{nr;Iu64}6MITY%M#Maz!%F}XRn>CB) z=EsowDx5?D>30GT)Z>EE$_#qhKs1?~(J4NfP|ba{`3cKdDRI4aGLQoXI}2$NNguMd zgb!~}9r}a*2u2#^x7vfWXwu@{$MkL>^P+!?OTBm2vT90v6C3aTQg6$g#*pXZhm|+n z1}Gb#^Vh@PJB$vU3XJ*D@u~aIW64E#_7S^pPw9)4htVX#(N(m=O!w-R(_ZMVli0)E{@9db%O)eO<2grnF_mZZ{K!UJ^}ETrsM zV&A*L(@SL~wH-nyKaxs?t95J&)V5~Y^o)taGQn6TML^NQ=5lH^aDA2p%XGu^WAYL% z{%9LR%VZkN%U@*Hz<8|*fd@QrvNlTyth>}X#7w%SJsMLkLIn0Fw@!B;PUHw0%mx4R zqsG3D1Zt_~6VA_cZ6 z#4GXfQqGT(X|-~b967rIkJoD@-m@9zmq91!zt=FtwG=eG+FG#unu%RHll~e@W#7cc z=|(Fehk!fe`-^OivA=m2%PAoDXt0d(oxtI2ZZU$euD|GGJKqoqmM9|YZe{?*|17H4 z(jafh4hdOUohWVi6H911h*T;NarB|)inOS7DDRP8wOyR)!avZ-D}_(E_#P#}QVmP~ zjI~K3`>3T&cVD{{1{?KNU-d7`^CTeX_QVP=$Q3J*_e0y_hwjlO_c6kNp4x0DaHBp)g9HWpN4=eK9zt4BEbA$1U_d zA~zXXA`?b_d-aPF#{3lI#!+WVymd#iOV8Q1U) zal<&f3(I8z91xQxeIMT&inoc=WP`6v;sI)T9u&sEEhIf6AG+E+4hW>f^|^tlUC4MG6ur-{15g zKmu^JaS;Jk;7HQ}Dn4DIbm zXe`%xU=xbs_2ay^aVHLQSx@3$9&JF=wh%83Yl&~vkg&0`#x{wQ=wXu*F}a0$6u!E< z4Q_Txw`=g$&^^L`(rt)a=M1`txF&Wnk&n%)4elWNx*|{QNm{(T>p7oW-`x7RYzaMm zmZ?;XTBBE!+WUD+Ue$d;SH|G-yq>{1dIrp>gD-^(Ys7UaR+e~KBho46)cmUE zw`qL`+IAlNZtqnL0R*R@+GLDsr4=f1jm+6pUW4DXZ0?Xo;Hz24zawg?>F@v@j&Lpo zC1#-6>3z)OmR7TyKjP?|NFBHD&5$v+;?yq5&s}VQj5N4qkis0@Rj(rr2nSRR^Jo6hbch5c77Hg)~I=fIyDr>iFH~UgfQ#o$Qyw`!u5t z4erVBxOL2F18REu->q;i|LF0mu`X-y-q>9J%cD}$x|_0Yaqpf%xEDDe&}Ssxtyw4f zk+%OKCVun)ejMgIg)jFqGEuD(A1_5)=iV2`yGMIoH@|qx6G!isl+!;HR86@4jtbE2 ziFOFJaa!u@@RA%)AUpDYs{kAh8QOeB?<8E}jP&v;{kQ@}FW%NSlF#`;6|m*~P`^p$BRoI0Eb^)YIE=)Skb(XL%eDVJuAYXsZ7-)CsiBe-`4I~>dGqfM>qL&q9FXD zkEv1T1fs0)&XOa!JdXZe=G4&Fl^Er_`|+VJ3@nb4y-W}6?tmsmX`B2m+`T7(S0-z4 zU!s1&H@C0>D$|9F;j_^AdTmLLtb2CS?zpWaJ)M*ZL`Lg0X0ql933Ph<${73#ZhsJ@ z07Svd2fX)}B`@ZlxVYm73@p8;W3t8hKxqqgY{3??9z!mL!HEu4$jNHi%{mNQu* z*+sHm2JiSU8}w6{M1D&1fTJQ2GFT!P8TB_vlv-@Y-e!0}0=An!1ln6N#&SRi`prDHTSY}! z6vo<5bMnAkRU}j>rx!NSYOe*kfuc@SSw(P$;c$6AGXy7Rc~4(j|kD|Zc- zcpg}J!XfK4AP{3XbRf?3e8*L45I#+PEyvtji=m_^j-MqUWgXXa@-F1maCEI}g^D6K z86&Hpq|fv}N^8Q?V}mXjh?!_1DTbVSSviCX9Wvy{$cQlY#Q+SjHXvCk{;$9Y;?$W- z1J7YZ*04GiwMo`Mecy-Q(wMJzKeC37T=ZsfRTvCJO!PknK0jWbihc7;F=Z;5WHHsd zWn|i#uG^ZPNaKll<08p`rkEaDQS(oMvGM$pJ8jVJkC|72KVBIp?`+`r)UmKfBDx^K zB!Nny8A^;DiUCs3C(A+il^|qMJAh zQt3n5rvH>UvRh7%XyjK8wn(w*kl}3cx6~x<`LF(GTac9v=i_r2f*x~9bXi433~q~6 zajxIOop^IEp7;GGxp%C;!cm7GqK7oT+OK*HIm5DaGx032c%uIw?*8(xiud~ig<-pC z>Fy5c?${uWgmfb; z+g%+}p=^|;e^R|gC)dMsd!8?a0rWKYeji?CScmSv^-VjxdUkN6OePR;nUNKs8d_{nf~fp7Q-(F*XsVs;13;PWwVW*7IkMz zBUd8zmmZzO&OvaSkm)XjDJ1F!s~Vy$A5ri9^QmNC{Zq_o#s+)@{f|Ett1+64bw|42 z;ki^{Q-5+MXbcD;i4x$It&#G!)~U^pA{F;i{`vSyoYzl<+W?p5k}vTagIf0ia})ZB zFz~#9Yz-)YkJdqV)#if|wg7E8N5zOtBo43*$YWnY^?@BlW#%+{UFLUn^!{`5`S;xJ z;^TRx(>E^%SEi?7rWw=Tc-3>QM_@hdMR{}7)fhwsF|4s?j{pI zV)0>;Uw6Gy9?a%7DD^rGk|$#NX&O(z^ua1vzOq z`XA!kO>C>5Tc@viI0R@v_U+pN_d5_Y){6O@Xc)XEsS%#-BC9E6T=m}zz?|ns6Lt`< z>(z_(F|sP>Z~Oj^Cf=7j$q{K-GHii4HSrwkJt?TTX|jItduunxT9Ld(9!|9o+$WKO zIwV)Lwrue$#$14=aC`XGR%$9joqXgXb=b)#;?C*05j)qI9QU#@rAUfj-F@9^V?pts zTH_Rq`HlEtIfrU}fxgl8G8Sq-JVsIERVUY1Up9SHOMQ;j34Fcdw}(|#3VRUK%Kaaq z7?1)K0UuE z?LAl+(fD;oY0B295W|x&P`b&8N)&8cZ|GsZ;8qTbTQGX>o0rT zz4Vmm(D41xLoX%#-c2;S+@U=Q5-WqCp(rm$Th)_w>_&co+EHqb)AH;djZUY?S0jI#BQQ9B=P>b!wEW z_eUj@dqi)RsiKDYj-Am6TW`5smEUR=Am^k7pKpalzt#_2YyTjc&l%OB`J&2*m`#{C zBFp$q6fz^rM_FlVzOMnk7H@U4gD<0F@L^w0jjlXo*OczAFUN$ZK-Jtwucb}0#?pILb|abae|d8;)s9%5S0Y}EODXQ`6N zAVPuR^hR#{w%-RwY%-j?zfmn|VmxZW1((?RoXNGEa7?5j-+Z^_mLDAl_@5 zziKMUo*vzdubgW;V~9=e?CTHg(#XQX+PY}hd7*c`IY$1bc>QJJ6=zrNY1}4(#7k)^P3J4a&sEip zRG-XvoQUyS8t~bYJ%c&D3vlQ$(XvYC>T*|?tkL*<`WVVAwyjkY+hu6q5eI}`9&x3g zEtB?f(lm+$eZN!6OdPsXaX&hV7xFK2tqkGPhtt`h%0zEnUf2^gXl&9y7#n9rqMcy% zOe(ce${cc6dsfv@M1<`qCWxgqDr6bE%_aPiNobxY>peL#Ym~4@HyH_6ktfzPWA~K{ z-IV-eU}to`qsmFbth>1=rX+APf#k5H*PUDcTUJ=uLV8%m#Gl`QIcj+ZcPh=mQwC$n zxm1kH-|n{nmcv}byKcGu3jybadNn&-O^+nt}mTjguh~n&2_qWT^f{J zLomMCA;X9|R{Afpj0J`~si>-OYv+RO0R zsg`W;#^rS$-Eyb)*Djbqo{TJxBjCu7B$FlQ+tJX zJ#b(@jK_Mol&V$ho~VY@s|Gw%o0jFVCOUpOLy05ePDHB|th)84hL0^a4;Rb&LAs<8 zuXhkSp62)6>xc>-^GiB?&!Hd*W7z(t3o^OZD%Idui%bzr!qRVcNOQ-1wk6-g=bRry z+d9gum|R<;eT)>#0WOlAS#`DUE0W4>XbC4=`1Dnr)ie!1+k-JhlQ2%)?}gIe4B->+ zT6age`9|JOT#rV7^N*e*|KVcQokrhdd)B|Uy54>H|L2ct?J)$T-?}&gH3%`U*>$l(D4b--FeQQ8p}LlG56H=Gylr1T%G~kP zXO11bcBX4VxInr6x%@k#Pb>IJw(R)p+E7KZQaVItxF)kf--BttzeM=v^-mX(*m0~V zO?NlEuZAX&0~IYQ57}<&+FUwPF@l)(S5Y!{^9T{Syf9PL@M0x}ovhaj(<7P>NDgN7 z$GIEL^sO$vv@4Rrc-#7nAyYWfs2F`lX&qTmGBlnhfpr(ZZwk+6@ZL?Q%f2ndw4Pbn zqZYhUunnFLiLtRIIL8WpX12z9qgH3OEY#i+08g$TOUtn^%zUUSApvf;*4!UZ_|%eT{8)3R?lk*T zx{?K}wRU(*JVYtyi<~g0iy)44{&1?eE>+OHJ5eIOfjOLt{F<3$b?Xkdpu;x%tk*f% zx>LG!?3w>n4>hhLtS^R{hLG?B`kuw5W}WWH!|spYBW;47%)Rx}blSBA;YZkzi|V#z z{;t>izNyoW@yLyV3atD*o=bB{YLwy60^A)(zKmT(knHoWuPZioB~)ZKo9CsS4Mg-d8d*JG7n_T&cEnGuI$B4}makOqEF zt;bGDoS6Z5yy2Bjt*>O82LAa_&FwcNA*pool~nL-YA@^C`e(oB!Z1s&nx=Bajx&vR~PbtUuA z`>2SCVi}DI^&I>j9l*7ct9j2i#xk`iIipAMs}3A!DB0kj@$oehPqO^pLBQU;xuqL5 zVxmuucDm>O9{Hn@EdVPK3j=|#O9pt7hI?%;>4>b};d8rx#2 zN4Ej(toG4BB+Brw`W6&7gaEMMJ00jU|3CsyzS`rQoDA zqhSAKktpE(D2|z;Sj@QY))>WR$5$n`_n$BM3N=?l~)rEtIPmhgRsRn7R&kv*e$O$KC%bt6JkKoYyKY*?)B^s_j(vkEwWZWcZ*++00 zEj6yC>1h3ctkm)0XzaMV7aLNYTd~4_B&PR=rnvQfwZ-MUOxvMyDE%Rs+aMgY<@mYs zHA9OpeOZUTe@Q$dm6UG`OZxkVXWk!w;~!It$wt0}WY{XFTcx=>b zvFY{$E6EqR})hqjbQre&-QSwiLOJQXJA=C0M| z+@{ z?!@(aCt1cdWQ>jUI=I-iq^W$5(A|<3x}hfX!9OH8V-WA<)c$2=+aglK{Wov7l6g0s zquk|pyda>RJ9qQp^jj?_x%}3kB-(xt@z)E{hWBmGo77xXpW@Bdu_`r3GOl3{?;Xv! zlhom)^O$xbn-Plo3sEyC#e3L6w@OB}I)fWBqaS&O*98FH&0Haa*xm5a|bp8kT5H{?u z``|99_j=!P7*R*Z&~RTUSABci8XTpzTM`8#2K@*!&{a2!CMcLegtt>t@xYaxWAwmf z&Blo2%RugbvBD!iO^P9P^3knoJB=jHMFF_SxVDs(in2%BkomKP;78d)cvh;%2=&oQbiAw{*-%LYSXh~Sib@AZPTian%T4CnWphEA;#V(v+Rl1!dKY?} zNm#)Mp~Gp{J#Bs77Y^%9=h^dt#U|^vG1{03S_9`jPGoErK zgSI;v3q+Nw7=-}$?FjV9-ndiS=^j+xEAm z^v#-D3roy-u(pYNHRc3O&QLO}+!~z7Yo54utjm z8^q{9-dCA+={h;uld?Pex;z$oU2xm8ePJlC4ALypucl*y@H*fvtkwR7Dqq7)eK>raVYp&2iD?q z*d-RiQ=`>}Lmr#aEQDMXXcY3jM(4cO*r@EiXoIDU!()R_i zJq0NEk^E<{Vy<&3-15vMef%SNdC&%~GV=0r$6ZO~9Of{cPCh3j|Lso&eR!L_K7``(d zB01kP*tL$dz0p~mpd^h*uXO7kaD5m2i0Z`<4^bK&%~>cvvEtrXlQ%uh$J9ajhBS!i zT&KZo171VMCYS4$1;H&hpBCkgBQep_Sl!*l}B>UTZ^O+jTqV0`j1(9_qK{; zczu_|X6K1CQd7#N_%UD3@VqN3uXR@joG_!8j6R?iS7*c*KbXu7nXhxYCyH?fQMjR0QtO5t@liDXP!wLQ&! zv%EQiDX%LFv-DLWVgw_|(1DY~q;DECUksz8qc)mPN<-P(bW0&_NpSmW{PKYRKG5H3IP@TaQ$=GHcw3kKMW0O| zB(I5{%weoeBDtkqaF(Td-f&VAW|T2HO$1I;_OKYKwO3DI9JV}0l-`x(qq2OK%WN(+ zu~?YU(zC*IyKZ2|3=D~uFgq~GrH6-q}*<{z2?^L<33UKXVj^Ph-@qR zl(m!QBZC%4gG;8Ba5Y5!i9TB&$I{93EdxDMGN0cKEKF{KfqZ>dOt=2jZWho}Tl>zfA4Mu(Qu?eR7QdK-4!#e_xoE;UO zG^Tg1l;7r^^%bxZjIrK54@>1s?EW`NBtJm8J@%x5AywuU>aPK4cl6s^&EMg8-t z5|7gfexH#8-_Y-Rp#`Hl>`_dEJ^XienU-oVv%<^raQfX%b=NG&|3v#{Z7PC<1yD`U%sX7&4VHX;?iogNKBqC#N{7n^ zVw;vSqeeI%Gr=fC`sIaRpDOiG?VcBs4puDLdMd1QBeZld6Di5JH@sg7BF{TpuB}4! zi_z10K$=}wUcM-#{@s&X9JS|Ul3BtqPSo<8o`O=vA7A5g6sK!HL}8$~)OgJ@s`NIK z$JaLN>lhNieQH^p>0OVinVM;1;W$bm9!e1_P9eZ&RO#smsmGk`NWLk>8}$XRFSV z>(HhMIIE(OGsS$ZqQc@JYxKRjtqWBpirUsg=O(iZU^=W|x{iG7`597@yJ zN5{AEs)f%_#%2$5?J_X7sE&n_$zC$PtDIb?jz?XoG4tRQyU(IH-iY&#HgiTZYq(F* zZ6wxX%~yZTRU|NC4$arVDKgwOmb8ug-SZ+{k9L@`D!eoK#JSvT+Bg0W^O`NB6VW9F zH0{`lvC50>W@FGuYzLJ}a7SP1bQxTCD9!Qa{OgO<0G~Gu1Kb8`LEE9LuQhOe-|O-X zd_yi9mt{G<9btg4)|-rXk<;+rXroPW#VLf>*IWTt%`oDYxyp;sPcs5zh5{&j1m7es zxeYEgN&U8&rXczGkVi?K={}llI#2j3h-H*|>{E>$0aiLl4?Bvs4W-zr`O4M29f7*O z>JGn#E4ah!eOVh$GxrCLsd2}kJah}xQZ$6;S8tPh*2JWzE>fl0kq)}6QolKs^f*bV zx-~0rvmRMut@0Hkwmv)Q8QLkfE}~5;RkdPHH7i!J1!fa+Bn}f_MJqddM_uo)<_DAc z=$Wa<6U5NObXzxI54XKId$csb9PX~~rXKn7^*g-1%`4T!Z$yO@GtG0HuZ1m@`sBC29ER-ji1l*5BKm@SQrAKmJPa!w-0itvz`Wx`SBv zx*LKyZB}4RYXxJy`ZlhU2tgz6ub52uKZ6Ca`+7AUK@9nGjFDVULQ6O(Tl!+XM|k9C zp{uCcG0DSQP2?F7`jBy2UujSD(DBKJuJ)u7i$U&z*+w#xF05yX%uog5s;_PFlxe-& z9A!ocI4*1@0|&2gBawhHdMl#9TtpZ|bvmfTJ6s|}_1IDg=C)ATu&o7$;6A6b%Ev=@ z{9g2)AWNAa3mo4o`v*6{D<*Yy;WocKuy0Adp0MKdZGX*)VbAVUDNFQScCH`RtEMd>`*}vhU({mk9 z!$oBr7rIa=$7*+kg#}CAOf7;h4;7a)du>CD(!LWPl8vg{;+G64s(qX?d5Q?nc^crK zuAl<+m^3-+#k_cSf7pipo~;uWuDsNKh00j6JEpPFyDJ-FrT_fI>6I;NjYyTNZLALq zM1md*nD-ab3eWir7MK9HPY+Wk|NFu-?Hyx#vG~h>0|Fyyo_?}0 zNxk^)cantMzr%m08PWr4*xARAM*cg{^Uu`COfV2K6JgL<;XwcW3T{+mY#^K?!;1PEJL%inVUX9X}IXMp>pVISDS|5*Vr2af_!Khp8C>i?_& z238QsFGj(#-B11hhXO4yFR>o%?(pLOICxqbFfXkyx7rB8_`ejOSWn6V2{+*UuWeG z&l5y5K0GhTrW+v)vHVY@4C#RGyQ}?~o<<|a__eG|6bl5{@jYMj)Su9pg?FZuAmX(f z(I{CfXMm-2dH98wT0QmVr?j*TG5@#LP(nT)eUmc>f&V0{&JNfdQ^R|49tsFG>{=(S zzk0$AqyNvBeeA59r`T2Ktgg>YGl?<$+j0x#bQUU{c_ey#->-@3^|Pa#-xonu|C%lf zxP!i4*OTZR3^J!Xew=H@=NBpx{I<5GzA!h^A`XkIa$K7U8=ynG0L#S$Pt4)$*Vn;M zvtLngN9eG{wf4c{WDP!{cYlA_=Z*Ah3+edasL%8j(C}e!oRTEG^tcAR3y#@3A@;A4 zxvRyZ>PPvvvTnDI_Df9~`MdYKXI61~F1x9Zk6x_D^-a6u&{fy1p1F@jzY}m8G7=pk z?J2(EnU5nRj9zKDvG}w!y`kEX+|Hz~ewGeOp{COk{2$3Q> z8Ai&^`uuq~ta6Y-T4!lCf;07UfQ7yy$j*w5O#6Ru%W%(iPbGrOeka_nZN>1CUQ?XVitgHA|!a|{8K5N~>^NVTBKohVH^ydDkQ;d)A< zseG$AT6$50VU}|ND3{U6_tRcUZBV-rn}E@^ai?erMuWZ?@-M%%#-LjbG|xL}tTL(zjt$ z@~ASzk!*4$@h3|w5ci|1ho?!V@aq@{SzI+qo$lQvsMS|&eY!_s^DK23(rdKu^!mOK z_NY^)>Z@4xqb+9>+tSXxWc2oI;(HsphO50H=ll1%PsWEh&IF0kDguF?GU|etY zM@~8l**?7aF`#RRVLVxS#?;Kaxc;J5!A{OytNK^Wo$I4NT4!298nGC@0f*fr|9Kcd zrGcTNUELtn#Yvh%308Tqe3`47ltoKP`3tM=+0RLjZ+pmBRyn_4&C;G6$ts5~*!Uad z&)d}5?xnKwMpFJ+25WRzdxuR_P$FPqBCt7&DY=>6riqHUD#YGj0 zhpi$v75;JuKRxBxb*Hgf1y~Cy2@wEU_7wxxY-pL-f*}imByJ?vym|FzTL+!8{8of{ zv!LMl_wRTfU%KZk7aaBJiCkRS%g=KgnsUgW{6z!s7cI;57R*oL5T^I~&lhNB1BGSr zN{xiZ1v;p5W}Bb$4t+Uif`^r<{a@WBSrgcl$}=JtZP>m6JZ|; zQTE0NYdtGcjvX($Eq@6`J*yH(0?;)x?i)%c1^S>0jJ{7DF@zy!KiR!6TI2BgB3n0O zyo5f+3=GL1s#Q3o5UXFXU}=@uV5Fp7v6SqNs`+QFoON1XEEvDt9K^lR%sDUEDiqJX zC^vr{BIDiOkn3`j`)HkoLir?p9we3Z$u3E1Fve#Iij;O#B3m&GH*H2=iBQ3m^2AGN zwy$q@+K#hc+}q6By4roPncyOiaq;y6sfhwld|ZB~P?=D*n!h=vFs^CU^Iec8>Sh<#CT zO^eM~p;LKf$(2prfJZQH!^Jtzq^6zic69c&a?q`>sEX%uWK`tAmhzLPH33cQSq3#= zKr$Oa>9_uyXc&4&hTB?VstWcNcb5{m_MNEd98t1&Ts8vvi@e4>Z<)|h7X;mpk{*}Z z6zgTKc&neptck3$t}DO-4uk;#uk9@y){;(}80RoK&^KaNbKA^fk%8;>Mjv>n8$Ce! z{px^Nge*};nRR!7i~4G5bm6U0Y7}5Y+%Ey&CoDP-0mz|%2PEO_Mt3RDk(3sHxmuq~ z*S&O&xGSD%TnWe|+K){$SVQB!@fU8HWJNC*;s5YRT3H4&x?ZtE1`8$ul8%d6wj4Gr z7!8ws(+%w=KCpe4f?2wljHK>Mn@ca8?osqJdNNmbC@J0ZduuB*?;WU+<%NSjh>{Zw z#BD|(Zf|$R@q(04-g>J}o=(vTGjBe#SuFa_+rM#9xQQLq#L3x`dw)=#o@h<-Cv}ie zL1MfR;eDlGU}eDJf}%EGh(?5rO@2UGmss~8ZQiTDxkXdh&j&j<4lEX$61jW+SE?#nM?K%$0ngBhI0RQ}^35u}k*9;0T|SR^!Pm+X_w%;Ksx zhF}Z>Sl1gOAWvF3@CN|eouUTFF5Q2{4#R}xcm@a zo-gn>1s&Adafx$hx8QS=jU8VP0~?~~#Ju=6DPaAdb^WN^tcfF^;=3yn!I@|?C|Q&U zJ76&1{@d#(Iv!7Ss&g%$=xD;0o_m=dRLrDl`1A32A>PUWVJ8nOvoB3P=mFr_&laRh zdTDJmCn3z8&i*{~j{Le=D)?~i=t&-`03kU!E;K+MKmGhBH!qxSQ{kIrH^xo0?-$hJ zEmXi54u${#xhaPMrb|b|!Nw&Z45Rf5pBx+PKc%u{Hb~6e2UF=MShI@pnOKJY#d#%r zAO|59z=jG=;|HXt?D-C{#+>>G(rfFuMm=Uavkn=+sSALxElnR;@g!(wM9IMo3rZyu zNf_uo(lJ}c{m=`-KUw8T0>daO>w=HCFu)}MV!%gV25|20&G_*D{soS00alathztY# z8sG}}SXTxjweNd*>Hq!(q;LjsI_wJv^M}II$0H#{-41BAuAy`%N*4N~I8 z4X;I~oFAO9+9UzH3}UhT>sQFLV~n3J4`#Ws&Ta1lId&;u__^K83Kul9eqa>r3i`+5 zD*#9eB|N_~#bp;d(j)LpV0vj<_EWx95qVzs&ORyeC?0f`=JY)Q8naq&KZYL9newdk z$ZBWTyJRx*ZSY?zf1yO7nKgh-N?g&rIaM}nzLur2!P#}D;PmCo(dT>g=xZI!UB~Nh zEKq4d>v0B9+@7EwDmnz=udze}hA{s_Ija>({ciFKY`u-5I!(6J#Sk^6Yrq0`J|XV7 zB>KYhvHX`sm_72G^HnI6E>dCY@5yf}0Tbzti<|iQgk!CZmyBfZeN!FKP|RDFw4@(> zGCz)5FXj2h%S_g})3s=2xU5to^?rBwcWEG2+J#kDxR;O zqpm-`>}zc{D!H_E*Jf&+Ih(-q-W=#vi;P(LQ&s?Rp&zg#MR?c3yX_Uu#w*v9^?RYj z4HlkypL*er%R>qkK22BK`^Ndj3LTS{{GS&&3%cc~EMZ9wf9)_+9AF$CR^TDiZ^p+< zFLUs!kA4n$zB5nO&e%O{|9)(ne!BL$d$%m&s_5t3{@upWHf^yqnh=!q-|_{XB&YZ# z4HhBrre48p!Bv{iR=qr?xJiqF)DSZu(AdM_VD6MNbjYXCA;Zx1ce>TcI>leN&<234 z&B3@CJ-dfar_6??pF$P(NqmfJUkvWRXI$}0EZJ|(3YvD)t1num+%A64#alZ5bC(jp zQETnwt8k-%)Cu(MPJUS z>`f>0&v{V+p1H^0b6S{R-EJ^)55A9860vGg(zLn$jCRrc(RyXnTNz_%G*OG>{l#?5|-9+Z}h|p=%ZD z_F@~7y_=hS(S1DRM0>rzIa;w~Xt9 zgL>D?l1)C`kYQGTNw$qUIztI_}73SlJ zg{*!Hai@od>hu1Kr5(CJ6t~ImS?q8w7_Q+Hr24P62P`E%yKh5JC8^_E0?hbolTtRv z-z8H-R{&1;efbOd;T^FNn?Q}ZC_2{PGy#;pKz#S~TvIMn)v*86uH`BD&*oNfGy5W@ zxUO3J^-!|;K2-i+zS0Cv(G?N7gv(E`s%K-Q`oEyw1AGyAwLJD5B<+<;nCw9CFK5Ua z0NLu|1u(~57u|x{Xes+&VoVIP5EUt(DJ!$5t zg)ywJgHt$T{hB@CA1y=@IsowzAPHGuF{tC&CGmP$TK75v@LaotAk3ed8z7qL2$+8l zYTBMSo1P|5o@f61kT`ab02Vt=qd>BvsyGa^AIN|7YQ{_9Ah?Yss)%(;Za`Um*?vej zy?kM3(mxO>RGI+=9B9@EOG4OMkCUnfzLN&;ua*OVgAySAToEse%CDmYAY<9xBNyXW zjyyF$-uV_V+Dq^&3^TU3RMG%{z+8a7(r00LYj8kBwygQ(%j?6I0bqYuXoYUAh~(;% z9T4FG?0^1wfYwrmBFY9rZzzRaBAO`x($_naszIb+7Xq#~)95%k2-3A#OG#8P=g6jq z06e@y3@~5(krwfVN*-trNdgcaQ)F0#A~VUy!RXs(vYTTP8bpdW?GPY>J`XfYm~MvwuE-kKtuo^GGT}~^t`mZ97c};4E+P3#uFXEr8vW?ReYaimI-;0 zU14|_L~TYDmIUUA@Cra_Ptqe7G9viY6(A>uTJ3MpYF<#UrK2fzZXLNQ=wLHwL>3;n)3KM)26zh6#L zT>Z|Vb*i7!)IOG}*_Q>Y#iDEFejDIR3RY_BjLI*PMsV&Ws`_j2L&sX0W>zH0~C`eEP?>VEy z2#+k<4t}aV9TWk;TT58aZPaS5K~c<6a@MSsPFIiW1NlC0WmOOm2yq3klhc*0T39xH z!U1sapFj||XoA7OYH$O|^4idm_ON`BQxCjC)PQ37E9AU_u>9D?X;+R277Un9QaQ91 z1T?!`@e(i7iHW>}TEuOu!2>xflf!t>89EHy`h*qZx$jhDfM6&%07knC2;bI$SQNa- z6Zi@);M3hg&nuODzRz5CdmuJYIlSp-*NUZms&n690l$`0nKsXd?8Tz^FxPW@n7*12 ziq|wsVtCw!f86p^X`%vAJ7M$9yXeS#7w225-h3BIwZUP<>V z`;%d^clsz5barL=N$Y@#Ndv@*vff%`_#GOa1nAE^^nEkY@>QhzI$dj@{E5LBmYRtX zOihgxC3xYWyK_1&Bk&YPxB(5?1wfIh2djAv;Uf_Sx5&E443!61I6 z1~7l5P!1i%Pp8SiN2;s+%RV-{qyYyZEP_}{3|S3|n$iwjRMOk1ywLB=gRvY z%S|b>%Im?2?cAPwAazs!lx9Bwa*n)IB*o_UGu?9Y(y+T5hrZ35CdAJhbU)bJCP0}@ zhlG=)Uo*7VwCoHR+12_Cw@=_Kjb)RfGDV5{FX9ieF}ZykKJ#+=(?Bz!|EY1g_Jbi2 z@oi~DN#z}CyX^?DYagYcJ)(z2WK8k10&;UI|n)dVodS4e`yiF=vi6 z6s@{lEbeL*+4IW#YPzEP`$H1pUSagHG3@IIGFOeK`>+q@bpidW86f%%UEX7Q`-41Z zioTh+9p!HXV%f*c5wtNcoJfSgD+-8^LZ3<53BFVoD9T5vSMrE{2BaKF9Gv@cNq>iP z1`Bj_A!TU?VUsO^cd!~)V6=%zx@a{^la~T)8^S!42jFln;3@CmW$$@sN@df?L z4j8SZvbp9;Kj*^f#@A0Qxs0V3qe7mdW-kfDr}8*cLlg}3k%xggN|0}ZMn4QvS$sv_ zQbyjdYI=*F`+!oL`jQy@3#Vd7qb2pEtYvI8xjoNdp*S3gnH ziQgty17ernwc1$Mu5@t}+xIBiHB}#3@gC_Om(4!Gfa-v(JuCXM%QC`G^!>)#Y4Y+_ zvC5UaN_!0*J4n2P3buSX%JsveRz@WQjRa5=%RD9RH1}WWt&o+H#UUTxl$KW#-tvdS zB+1^&sUbi)*kUrcv|Vd+;EBxY`{SuB4Tp(yx;sN}{Jpp=aba zde|Ol{SdIfII!yJc#>DgXBaJ~UYcucC_ET>0pIqbb=l0La2NHLVlK3d9~b%x*`1|S zEURN^eH@b;)Ck11p@Z>Q?O!0z{vu4Bz?IpKGo>Uim-dYF>+oQRE=boa>!>z8Y4SS! zsSJDt-~^#B$affTArziA$x9b&w5M-od45HZq9pM~qvunx$N5c7dg|SIB#H2-2}S-@ zgR))hZ1_g1-&2b?6WNzOBx4QmuG9jE?$!E0r^QRao&@Me%?O_ZVHs$eGd1#1jDn#v z$lHe+?U9p{6VgVs-p_y3kq^HFT72!feS2QEX(X!>K$E^~UGO&?#lt!n&2WO{ck6ul zUE8{}IgJ+hS3@k5mLtMCbK*Sv`c{yfJ1_5*nF;?R{c3C0Mw|G1K^bi74DZ5Xt1TVC7gM7WV4=kYI&+Rp4zCh ztJ_JU7_zz)y05cD7#^;^_L>U=u{l!{_OQQHBh(eKi{a-?wZ;3!PLhNAI#E2+dgnlh z3CK`k5dHi{3zeRi;@K0FbODO$NhIm_;8iSb=V6UIAu;!ED<7|3%Y-c{E%zCWzHmQa zH{c6WA_NoCAqPt){N8C+Zk89CWoslL!mRPwug)agWjePGyi*Z0d-k!hRm-t?&X{u_ z$m=QKhFF`icNk&SptM0PF~NNPd)-FwmDiS-vcg;-!*9NvT;H$&K+g{pWPAJLaSgVh zrmfxAz)!*@^zK;X4U>9;{7OOTM%OZWrqrxYiRTs2uzK}T46{NqbFF1!N;b=@^0Kvv zmJ$;lv<9x(TH>-pAb$d&D1dXYq~b_OWaez0Ua;7f=I=@vW1xadu%eeZYcA`3=88Te z!UNj=3?xc7EF4$LH~x^l#$sPpRFvKU8@0!UAoowOP}z>N7EB;J6QTka?{Edc!<^-( z>r_1L>E_Mc$QTd%c!Xa*+uY#(IqK!Ry91;k*(V@X2wXhBZUqsfiP)!64Iz^is{J`x z*BR=E_}vP&QO`JP42A}1(f-@cE7${(Zj}l&PcPO@xFDP=>vgQj+s&$VTmuFW2N;0j zD{hGnH0WhI&(@9Y!BQnPQMQ9xM|i^*J{@X5$Rq$)t9ebk_F5oY9>pUkdUIs1WFS9v za83RTC$$($ptDw>1*Aqpj#=tAP`{GgJF@cW)30z@7#~eRJq152;&tJqF0zTB%@ozeBu*QxfYL&SK3 z{1jF|(*D{_hz=!y6HF@i8Mm=%<>+DEdD>Y7B%%)lo=p=Xx$oxC;q-}&Q(fJ3ry0Nb z|Jn(k833Pt9Wa7urjpsscFw4ioACsXp00}q80V=XgaQG?B9ipjVQ=L@gHRX^`mdm> z1c>&0m!(Ji%0{u5^!xSgYYf=`zHtS^Zk ztMCsh0gB@)Kdoc(XV3m#?N8z62T2Fl74orQU&TE@Lq7? zODk}>#><(IAZ)cY0q2uwcptrfe`&<-_&B{)aT@g6Jk(;J%a@8h0m6fLfj!bTEqHR> zrn<4!J}Y$H8FFXt7zM4cHY6Y<^jIGjvR~po;m>$#PJRWfCJxV17$`74AMdMLYXL=0P@MUY)^TDF!GdXRV+fYx^n_IiXKk2 z*4svLlZQCwE`@Nwuvvg~WMR|xiPsl2Xs!5y(Hfsw+aa?rx1&^JD9v@$jp|kma<(-x zGX4n5m?YnN_yg+;l^-M)U`EcG3l9{G!Yuk>YTavdIIUPX%GZp3%J}Fr{G92M#bz8)UWkQ??_-Bp@Rj{-N7QNJ$Ia%g~nz;Z1+lN5M?_ z2PmMBe9$;#*K&*t0^AUzLKUdb2COIdOrxQ^o|+z3Q}2jw!{F$l(=|NeY90`aV;P|oQ8J)#M)tIL53 zhCW56Kj8@@A7C#v`5eIOe~-Kg1X{iS-xKOM2lag3A#V9lGwI6XBK>#&f)i*sq^$H) zJG+5DQWU(Hv98rs6Z+TSbOT(oWrY1^L*k9Iv-*&80Jt|T3WL5faATe>Jg`qhHhU5>XJ)` zIchik*B_(c0?n62e<`E_65~^fc}h>ZfDUaEvPu65+z(;_!~!lZ4RGlHDM96F|G!kV z<{vYF@q`0MEb>ADVDujySg>WGTR8t^DY}rYev;xj-$? zskqdnG7(8|J}tUxGUK7QoG^RN>6|AoZEs-wch?Cb#c>g^!C8!Vj|#g7H#rbR6vOlV~kVf0Kc;SHG4P`$z5n z>FL_TnO@^~W@9>GQ=25=go6}OR4U6oa?K^=G(DY6hg{ktbkUD$4yMx_%3W@e(uFp2 zoh~jRMi!D5i=Fhiv?upC-=9Cu{@e3x@7{fH@Av!pe4gJM27;eEp%{z`VftWbGhB^O z?@wC49HArKdo*D!@cx&%?9uNY9E|BF4Ye&M4?fi-FxJgQx7@Q=hl&HV==sdWWG01) zX_$Kd&bVfz{U&8A<_O^xU;YYegfhA5Q?K5MRW>7oxatR9wWOV+;MzAcbZbNS5sCxY zLa)ih0P_Q=x$Aw;`UWe~8)&0!N>Gu=blm{-H)G%%6N?*K!Z-@|q?gIh#eKde7wPnO zIE9E~6e^9Ti@0sZfE#JKuoX%0zbeQHoQ#Z&hexY3+h(b7bVy*7p|JFolyG&sk+Jc~ zsh}z}h8`+W>ov0&qsabWcBVNTC-aWawGyHC>E~RW z63Ob4M>T35~ z!<#h>0fNrDlcA*u?uD~t=?l_4o_i@WJrIr(fCHgmROCo3J~mpu!e3bB?x@Bsi?SF z#Y;o}#WtIX`}!8znfGIS+JYBHw!-K0-5|?tar@N~pY;bN$@>57Xw3dHkbRR9f^qw- zLaH{YC)cotOG49LZSJ+>p**q>6fi^HJLgp~f35GxGAmvEX;y6Aa>fXosYj@{k6ROB z*j&?o6`UbAg2u1$E+Z)4GaK;gK%W9lAeQzHwk5t1p7Dgdy?y4{VjjfsNc zHCbLTFxk(8Oi`qV(0Z5GEzH-K@O+xjGQ)^raE`xcM(a4DTZlx&T(z#ppd55@+bJG{GN}Ep9 zMuv!^x7{lGjrP{{hun3354D(;=;abMvoNlBvWfYemlk%pE9vR!3PTHDNT3E>H7jds zLEF3?H~Vvz6Hx3vv)8-QAWx6;0v_;X`#M;uJ&u(0I)FoOBTHdfU@?Q0%RA3dtB|X zj@@=@ANT|Nzj_JIOl0!1xsq9TVU6j8D2Z|as4b_K95>=!4DSnFhirftI7@qm?^8oO%MUNtA2OVbc2Nq=j<8ER)~hsq z<&;{ui1=xF%&al|sPAs0U7(%=Ey2Wac51jSc317U?{jl=Q>*Zp65g+gACr%52}s$P z;3W@@`O5JN=SZt|# zc{l7fbB36D3FA8V#ixkZ0249Y@gV#|TXX^?} GYTSR0nC~0_ literal 0 HcmV?d00001 diff --git a/Macros/Options/logo.svg b/Macros/Options/logo.svg new file mode 100644 index 0000000..0345444 --- /dev/null +++ b/Macros/Options/logo.svg @@ -0,0 +1,551 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Macros/Options/project.yml b/Macros/Options/project.yml new file mode 100644 index 0000000..abfabb5 --- /dev/null +++ b/Macros/Options/project.yml @@ -0,0 +1,13 @@ +name: Options +settings: + LINT_MODE: ${LINT_MODE} +packages: + StealthyStash: + path: . +aggregateTargets: + Lint: + buildScripts: + - path: Scripts/lint.sh + name: Lint + basedOnDependencyAnalysis: false + schemes: {} \ No newline at end of file diff --git a/Macros/SKSampleMacro/.gitignore b/Macros/SKSampleMacro/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/Macros/SKSampleMacro/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Macros/SKSampleMacro/Package.resolved b/Macros/SKSampleMacro/Package.resolved new file mode 100644 index 0000000..25225ed --- /dev/null +++ b/Macros/SKSampleMacro/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "9eace0238bc49301f22ac682c8f3e981d6f1a63573efd4e1a727b71527c4ebb0", + "pins" : [ + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-syntax.git", + "state" : { + "revision" : "f99ae8aa18f0cf0d53481901f88a0991dc3bd4a2", + "version" : "601.0.1" + } + } + ], + "version" : 3 +} diff --git a/Macros/SKSampleMacro/Package.swift b/Macros/SKSampleMacro/Package.swift new file mode 100644 index 0000000..b0688ff --- /dev/null +++ b/Macros/SKSampleMacro/Package.swift @@ -0,0 +1,59 @@ +// swift-tools-version: 6.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription +import CompilerPluginSupport + +let package = Package( + name: "SKSampleMacro", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .watchOS(.v6), + .tvOS(.v13), + .visionOS(.v1) + ], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "SKSampleMacro", + targets: ["SKSampleMacro"] + ), + .executable( + name: "SKSampleMacroClient", + targets: ["SKSampleMacroClient"] + ), + ], + dependencies: [ + .package(path: "../.."), + .package(url: "https://github.com/apple/swift-syntax.git", from: "601.0.1") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + // Macro implementation that performs the source transformation of a macro. + .macro( + name: "SKSampleMacroMacros", + dependencies: [ + .product(name: "SyntaxKit", package: "SyntaxKit"), + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax") + ] + ), + + // Library that exposes a macro as part of its API, which is used in client programs. + .target(name: "SKSampleMacro", dependencies: ["SKSampleMacroMacros"]), + + // A client of the library, which is able to use the macro in its own code. + .executableTarget(name: "SKSampleMacroClient", dependencies: ["SKSampleMacro"]), + + // A test target used to develop the macro implementation. + .testTarget( + name: "SKSampleMacroTests", + dependencies: [ + "SKSampleMacroMacros", + .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + ] + ), + ] +) diff --git a/Macros/SKSampleMacro/Sources/SKSampleMacro/SKSampleMacro.swift b/Macros/SKSampleMacro/Sources/SKSampleMacro/SKSampleMacro.swift new file mode 100644 index 0000000..d812512 --- /dev/null +++ b/Macros/SKSampleMacro/Sources/SKSampleMacro/SKSampleMacro.swift @@ -0,0 +1,11 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +/// A macro that produces both a value and a string containing the +/// source code that generated the value. For example, +/// +/// #stringify(x + y) +/// +/// produces a tuple `(x + y, "x + y")`. +@freestanding(expression) +public macro stringify(_ lhs: T, _ rhs: T) -> (T, String) = #externalMacro(module: "SKSampleMacroMacros", type: "StringifyMacro") diff --git a/Macros/SKSampleMacro/Sources/SKSampleMacroClient/main.swift b/Macros/SKSampleMacro/Sources/SKSampleMacroClient/main.swift new file mode 100644 index 0000000..1fdb254 --- /dev/null +++ b/Macros/SKSampleMacro/Sources/SKSampleMacroClient/main.swift @@ -0,0 +1,8 @@ +import SKSampleMacro + +let a = 17 +let b = 25 + +let (result, code) = #stringify(a, b) + +print("The value \(result) was produced by the code \"\(code)\"") diff --git a/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift b/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift new file mode 100644 index 0000000..014fb7e --- /dev/null +++ b/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift @@ -0,0 +1,42 @@ +import SwiftCompilerPlugin +import SwiftSyntax +//import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SyntaxKit + +/// Implementation of the `stringify` macro, which takes an expression +/// of any type and produces a tuple containing the value of that expression +/// and the source code that produced the value. For example +/// +/// #stringify(x + y) +/// +/// will expand to +/// +/// (x + y, "x + y") +public struct StringifyMacro: ExpressionMacro { + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) -> ExprSyntax { + let first = node.arguments.first?.expression + let second = node.arguments.last?.expression + guard let first, let second else { + fatalError("compiler bug: the macro does not have any arguments") + } + + return Tuple{ + Infix("+") { + VariableExp(first.description) + VariableExp(second.description) + } + Literal.string("\(first.description) + \(second.description)") + }.expr + } +} + +@main +struct SKSampleMacroPlugin: CompilerPlugin { + let providingMacros: [Macro.Type] = [ + StringifyMacro.self, + ] +} diff --git a/Macros/SKSampleMacro/Tests/SKSampleMacroTests/SKSampleMacroTests.swift b/Macros/SKSampleMacro/Tests/SKSampleMacroTests/SKSampleMacroTests.swift new file mode 100644 index 0000000..ca69367 --- /dev/null +++ b/Macros/SKSampleMacro/Tests/SKSampleMacroTests/SKSampleMacroTests.swift @@ -0,0 +1,48 @@ +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftSyntaxMacrosTestSupport +import XCTest + +// Macro implementations build for the host, so the corresponding module is not available when cross-compiling. Cross-compiled tests may still make use of the macro itself in end-to-end tests. +#if canImport(SKSampleMacroMacros) +import SKSampleMacroMacros + +let testMacros: [String: Macro.Type] = [ + "stringify": StringifyMacro.self, +] +#endif + +final class SKSampleMacroTests: XCTestCase { + func testMacro() throws { + #if canImport(SKSampleMacroMacros) + assertMacroExpansion( + """ + #stringify(a + b) + """, + expandedSource: """ + (a + b, "a + b") + """, + macros: testMacros + ) + #else + throw XCTSkip("macros are only supported when running tests for the host platform") + #endif + } + + func testMacroWithStringLiteral() throws { + #if canImport(SKSampleMacroMacros) + assertMacroExpansion( + #""" + #stringify("Hello, \(name)") + """#, + expandedSource: #""" + ("Hello, \(name)", #""Hello, \(name)""#) + """#, + macros: testMacros + ) + #else + throw XCTSkip("macros are only supported when running tests for the host platform") + #endif + } +} diff --git a/Package.resolved b/Package.resolved index 9a2ef48..fc91c87 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "b5881f7ff763cf360a3639d99029de2b3ab4a457e0d8f08ce744bae51c2bf670", + "originHash" : "79e6b2b96efe3d22ee340e623938e0363d6ce8fb0edfd7ccdf90e98b766f59ec", "pins" : [ { "identity" : "swift-syntax", diff --git a/Sources/SyntaxKit/CodeBlock+ExprSyntax.swift b/Sources/SyntaxKit/CodeBlock+ExprSyntax.swift new file mode 100644 index 0000000..b8b9f30 --- /dev/null +++ b/Sources/SyntaxKit/CodeBlock+ExprSyntax.swift @@ -0,0 +1,51 @@ +// +// CodeBlock+ExprSyntax.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension CodeBlock { + /// Attempts to treat this `CodeBlock` as an expression and return its `ExprSyntax` form. + /// + /// If the underlying syntax already *is* an `ExprSyntax`, it is returned directly. If the + /// underlying syntax is a bare `TokenSyntax` (commonly the case for `VariableExp` which + /// produces an identifier token), we wrap it in a `DeclReferenceExprSyntax` so that it becomes + /// a valid expression node. Any other kind of syntax results in a runtime error, because it + /// cannot be represented as an expression (e.g. declarations or statements). + public var expr: ExprSyntax { + if let expr = self.syntax.as(ExprSyntax.self) { + return expr + } + + if let token = self.syntax.as(TokenSyntax.self) { + return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) + } + + fatalError("CodeBlock of type \(type(of: self.syntax)) cannot be represented as ExprSyntax") + } +} diff --git a/Sources/SyntaxKit/Extension.swift b/Sources/SyntaxKit/Extension.swift new file mode 100644 index 0000000..522c5fc --- /dev/null +++ b/Sources/SyntaxKit/Extension.swift @@ -0,0 +1,96 @@ +// +// Extension.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift `extension` declaration. +public struct Extension: CodeBlock { + private let extendedType: String + private let members: [CodeBlock] + private var inheritance: [String] = [] + + /// Creates an `extension` declaration. + /// - Parameters: + /// - extendedType: The name of the type being extended. + /// - content: A ``CodeBlockBuilder`` that provides the members of the extension. + public init(_ extendedType: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.extendedType = extendedType + self.members = content() + } + + /// Sets the inheritance for the extension. + /// - Parameter types: The types to inherit from. + /// - Returns: A copy of the extension with the inheritance set. + public func inherits(_ types: String...) -> Self { + var copy = self + copy.inheritance = types + return copy + } + + public var syntax: SyntaxProtocol { + let extensionKeyword = TokenSyntax.keyword(.extension, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(extendedType, trailingTrivia: .space) + + var inheritanceClause: InheritanceClauseSyntax? + if !inheritance.isEmpty { + let inheritedTypes = inheritance.map { type in + InheritedTypeSyntax(type: IdentifierTypeSyntax(name: .identifier(type))) + } + inheritanceClause = InheritanceClauseSyntax( + colon: .colonToken(), + inheritedTypes: InheritedTypeListSyntax( + inheritedTypes.enumerated().map { idx, inherited in + var type = inherited + if idx < inheritedTypes.count - 1 { + type = type.with(\.trailingComma, TokenSyntax.commaToken(trailingTrivia: .space)) + } + return type + } + ) + ) + } + + let memberBlock = MemberBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + members: MemberBlockItemListSyntax( + members.compactMap { member in + guard let syntax = member.syntax.as(DeclSyntax.self) else { return nil } + return MemberBlockItemSyntax(decl: syntax, trailingTrivia: .newline) + }), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + return ExtensionDeclSyntax( + extensionKeyword: extensionKeyword, + extendedType: IdentifierTypeSyntax(name: identifier), + inheritanceClause: inheritanceClause, + memberBlock: memberBlock + ) + } +} diff --git a/Sources/SyntaxKit/Infix.swift b/Sources/SyntaxKit/Infix.swift new file mode 100644 index 0000000..ad18e0d --- /dev/null +++ b/Sources/SyntaxKit/Infix.swift @@ -0,0 +1,70 @@ +// +// Infix.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A generic binary (infix) operator expression, e.g. `a + b`. +public struct Infix: CodeBlock { + private let op: String + private let operands: [CodeBlock] + + /// Creates an infix operator expression. + /// - Parameters: + /// - op: The operator symbol as it should appear in source (e.g. "+", "-", "&&"). + /// - content: A ``CodeBlockBuilder`` that supplies the two operand expressions. + /// + /// Exactly two operands must be supplied – a left-hand side and a right-hand side. + public init(_ op: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.op = op + self.operands = content() + } + + public var syntax: SyntaxProtocol { + guard operands.count == 2 else { + fatalError("Infix expects exactly two operands, got \(operands.count).") + } + + let left = operands[0].expr + let right = operands[1].expr + + let operatorExpr = ExprSyntax( + BinaryOperatorExprSyntax( + operator: .binaryOperator(op, leadingTrivia: .space, trailingTrivia: .space) + ) + ) + + return SequenceExprSyntax( + elements: ExprListSyntax([ + left, + operatorExpr, + right, + ]) + ) + } +} diff --git a/Sources/SyntaxKit/Literal.swift b/Sources/SyntaxKit/Literal.swift index 7e0e1dd..0cec486 100644 --- a/Sources/SyntaxKit/Literal.swift +++ b/Sources/SyntaxKit/Literal.swift @@ -29,6 +29,15 @@ import SwiftSyntax +/// A protocol for types that can be represented as literal values in Swift code. +public protocol LiteralValue { + /// The Swift type name for this literal value. + var typeName: String { get } + + /// Renders this value as a Swift literal string. + var literalString: String { get } +} + /// A literal value. public enum Literal: CodeBlock { /// A string literal. @@ -64,3 +73,43 @@ public enum Literal: CodeBlock { } } } + +// MARK: - LiteralValue Implementations + +extension Array: LiteralValue where Element == String { + public var typeName: String { "[String]" } + + public var literalString: String { + let elements = self.map { element in + // Escape quotes and newlines + let escaped = + element + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + .replacingOccurrences(of: "\n", with: "\\n") + .replacingOccurrences(of: "\r", with: "\\r") + .replacingOccurrences(of: "\t", with: "\\t") + return "\"\(escaped)\"" + }.joined(separator: ", ") + return "[\(elements)]" + } +} + +extension Dictionary: LiteralValue where Key == Int, Value == String { + public var typeName: String { "[Int: String]" } + + public var literalString: String { + let elements = self.map { key, value in + // Escape quotes and newlines + let escaped = + value + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + .replacingOccurrences(of: "\n", with: "\\n") + .replacingOccurrences(of: "\r", with: "\\r") + .replacingOccurrences(of: "\t", with: "\\t") + return "\(key): \"\(escaped)\"" + }.joined(separator: ", ") + return "[\(elements)]" + } +} diff --git a/Sources/SyntaxKit/Tuple.swift b/Sources/SyntaxKit/Tuple.swift new file mode 100644 index 0000000..6179f7c --- /dev/null +++ b/Sources/SyntaxKit/Tuple.swift @@ -0,0 +1,71 @@ +// +// Tuple.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A tuple expression, e.g. `(a, b, c)`. +public struct Tuple: CodeBlock { + private let elements: [CodeBlock] + + /// Creates a tuple expression comprising the supplied elements. + /// - Parameter content: A ``CodeBlockBuilder`` producing the tuple elements **in order**. + /// Elements may be any `CodeBlock` that can be represented as an expression (see + /// `CodeBlock.expr`). + public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.elements = content() + } + + public var syntax: SyntaxProtocol { + guard !elements.isEmpty else { + fatalError("Tuple must contain at least one element.") + } + + let list = TupleExprElementListSyntax( + elements.enumerated().map { index, block in + let elementExpr = block.expr + return TupleExprElementSyntax( + label: nil, + colon: nil, + expression: elementExpr, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + + let tupleExpr = ExprSyntax( + TupleExprSyntax( + leftParen: .leftParenToken(), + elements: list, + rightParen: .rightParenToken() + ) + ) + + return tupleExpr + } +} diff --git a/Sources/SyntaxKit/TypeAlias.swift b/Sources/SyntaxKit/TypeAlias.swift new file mode 100644 index 0000000..7f8672b --- /dev/null +++ b/Sources/SyntaxKit/TypeAlias.swift @@ -0,0 +1,65 @@ +// +// TypeAlias.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift `typealias` declaration. +public struct TypeAlias: CodeBlock { + private let name: String + private let existingType: String + + /// Creates a `typealias` declaration. + /// - Parameters: + /// - name: The new name that will alias the existing type. + /// - type: The existing type that is being aliased. + public init(_ name: String, equals type: String) { + self.name = name + self.existingType = type + } + + public var syntax: SyntaxProtocol { + // `typealias` keyword token + let keyword = TokenSyntax.keyword(.typealias, trailingTrivia: .space) + + // Alias identifier + let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) + + // Initializer clause – `= ExistingType` + let initializer = TypeInitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: IdentifierTypeSyntax(name: .identifier(existingType)) + ) + + return TypeAliasDeclSyntax( + typealiasKeyword: keyword, + name: identifier, + initializer: initializer + ) + } +} diff --git a/Sources/SyntaxKit/Variable.swift b/Sources/SyntaxKit/Variable.swift index b37ec0d..40140ba 100644 --- a/Sources/SyntaxKit/Variable.swift +++ b/Sources/SyntaxKit/Variable.swift @@ -35,6 +35,7 @@ public struct Variable: CodeBlock { private let name: String private let type: String private let defaultValue: String? + private var isStatic: Bool = false /// Creates a `let` or `var` declaration with an explicit type. /// - Parameters: @@ -50,6 +51,26 @@ public struct Variable: CodeBlock { self.defaultValue = defaultValue } + /// Creates a `let` or `var` declaration with a literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - value: A literal value that conforms to ``LiteralValue``. + public init(_ kind: VariableKind, name: String, equals value: T) { + self.kind = kind + self.name = name + self.type = value.typeName + self.defaultValue = value.literalString + } + + /// Marks the variable as `static`. + /// - Returns: A copy of the variable marked as `static`. + public func `static`() -> Self { + var copy = self + copy.isStatic = true + return copy + } + public var syntax: SyntaxProtocol { let bindingKeyword = TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) @@ -65,7 +86,15 @@ public struct Variable: CodeBlock { ) } + var modifiers: DeclModifierListSyntax = [] + if isStatic { + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) + ]) + } + return VariableDeclSyntax( + modifiers: modifiers, bindingSpecifier: bindingKeyword, bindings: PatternBindingListSyntax([ PatternBindingSyntax( diff --git a/Tests/SyntaxKitTests/ExtensionTests.swift b/Tests/SyntaxKitTests/ExtensionTests.swift new file mode 100644 index 0000000..b04190d --- /dev/null +++ b/Tests/SyntaxKitTests/ExtensionTests.swift @@ -0,0 +1,180 @@ +// +// ExtensionTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyntaxKit + +struct ExtensionTests { + // MARK: - Basic Extension Tests + + @Test func testBasicExtension() { + let extensionDecl = Extension("String") { + Variable(.let, name: "test", type: "Int", equals: "42") + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension String")) + #expect(generated.contains("let test: Int = 42")) + } + + @Test func testExtensionWithMultipleMembers() { + let extensionDecl = Extension("Array") { + Variable(.let, name: "isEmpty", type: "Bool", equals: "true") + Variable(.let, name: "count", type: "Int", equals: "0") + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension Array")) + #expect(generated.contains("let isEmpty: Bool = true")) + #expect(generated.contains("let count: Int = 0")) + } + + // MARK: - Extension with Inheritance Tests + + @Test func testExtensionWithSingleInheritance() { + let extensionDecl = Extension("MyEnum") { + TypeAlias("MappedType", equals: "String") + }.inherits("MappedValueRepresentable") + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension MyEnum: MappedValueRepresentable")) + #expect(generated.contains("typealias MappedType = String")) + } + + @Test func testExtensionWithMultipleInheritance() { + let extensionDecl = Extension("MyEnum") { + TypeAlias("MappedType", equals: "String") + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains("extension MyEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + } + + @Test func testExtensionWithoutInheritance() { + let extensionDecl = Extension("MyType") { + Variable(.let, name: "constant", type: "String", equals: "value") + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension MyType")) + #expect(!generated.contains("extension MyType:")) + #expect(generated.contains("let constant: String = value")) + } + + // MARK: - Extension with Complex Members Tests + + @Test func testExtensionWithStaticVariables() { + let array: [String] = ["a", "b", "c"] + let dict: [Int: String] = [1: "one", 2: "two"] + + let extensionDecl = Extension("TestEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: array).static() + Variable(.let, name: "lookup", equals: dict).static() + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains("extension TestEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [String] = [\"a\", \"b\", \"c\"]")) + #expect(generated.contains("static let lookup: [Int: String]")) + #expect(generated.contains("1: \"one\"")) + #expect(generated.contains("2: \"two\"")) + } + + @Test func testExtensionWithFunctions() { + let extensionDecl = Extension("String") { + Function("uppercasedFirst", returns: "String") { + Return { + VariableExp("self.prefix(1).uppercased() + self.dropFirst()") + } + } + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension String")) + #expect(generated.contains("func uppercasedFirst() -> String")) + #expect(generated.contains("return self.prefix(1).uppercased() + self.dropFirst()")) + } + + // MARK: - Edge Cases + + @Test func testExtensionWithEmptyBody() { + let extensionDecl = Extension("EmptyType") { + // Empty body + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension EmptyType")) + #expect(generated.contains("{")) + #expect(generated.contains("}")) + } + + @Test func testExtensionWithSpecialCharactersInName() { + let extensionDecl = Extension("MyType") { + Variable(.let, name: "generic", type: "T", equals: "nil") + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension MyType")) + #expect(generated.contains("let generic: T = nil")) + } + + @Test func testInheritsMethodReturnsNewInstance() { + let original = Extension("Test") { + Variable(.let, name: "value", type: "Int", equals: "42") + } + + let withInheritance = original.inherits("Protocol1", "Protocol2") + + // Should be different instances + #expect(original.generateCode() != withInheritance.generateCode()) + + // Original should not have inheritance + let originalGenerated = original.generateCode().normalize() + #expect(!originalGenerated.contains("extension Test:")) + + // With inheritance should have inheritance + let inheritedGenerated = withInheritance.generateCode().normalize() + #expect(inheritedGenerated.contains(": Protocol1, Protocol2")) + } +} diff --git a/Tests/SyntaxKitTests/LiteralValueTests.swift b/Tests/SyntaxKitTests/LiteralValueTests.swift new file mode 100644 index 0000000..1517dcb --- /dev/null +++ b/Tests/SyntaxKitTests/LiteralValueTests.swift @@ -0,0 +1,111 @@ +// +// LiteralValueTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyntaxKit + +struct LiteralValueTests { + // MARK: - Array LiteralValue Tests + + @Test func testArrayStringTypeName() { + let array: [String] = ["a", "b", "c"] + #expect(array.typeName == "[String]") + } + + @Test func testArrayStringLiteralString() { + let array: [String] = ["a", "b", "c"] + #expect(array.literalString == "[\"a\", \"b\", \"c\"]") + } + + @Test func testEmptyArrayStringLiteralString() { + let array: [String] = [] + #expect(array.literalString == "[]") + } + + @Test func testArrayStringWithSpecialCharacters() { + let array: [String] = ["hello world", "test\"quote", "line\nbreak"] + #expect(array.literalString == "[\"hello world\", \"test\\\"quote\", \"line\\nbreak\"]") + } + + // MARK: - Dictionary LiteralValue Tests + + @Test func testDictionaryIntStringTypeName() { + let dict: [Int: String] = [1: "a", 2: "b"] + #expect(dict.typeName == "[Int: String]") + } + + @Test func testDictionaryIntStringLiteralString() { + let dict: [Int: String] = [1: "a", 2: "b", 3: "c"] + let literal = dict.literalString + + // Dictionary order is not guaranteed, so check that all elements are present + #expect(literal.contains("1: \"a\"")) + #expect(literal.contains("2: \"b\"")) + #expect(literal.contains("3: \"c\"")) + #expect(literal.hasPrefix("[")) + #expect(literal.hasSuffix("]")) + } + + @Test func testEmptyDictionaryLiteralString() { + let dict: [Int: String] = [:] + #expect(dict.literalString == "[]") + } + + @Test func testDictionaryWithSpecialCharacters() { + let dict: [Int: String] = [1: "hello world", 2: "test\"quote"] + let literal = dict.literalString + + // Dictionary order is not guaranteed, so check that all elements are present + #expect(literal.contains("1: \"hello world\"")) + #expect(literal.contains("2: \"test\\\"quote\"")) + #expect(literal.hasPrefix("[")) + #expect(literal.hasSuffix("]")) + } + + // MARK: - Dictionary Ordering Tests + + @Test func testDictionaryOrderingIsConsistent() { + let dict1: [Int: String] = [2: "b", 1: "a", 3: "c"] + let dict2: [Int: String] = [1: "a", 2: "b", 3: "c"] + + // Both should produce the same literal string regardless of insertion order + let literal1 = dict1.literalString + let literal2 = dict2.literalString + + // The exact order depends on the dictionary's internal ordering, + // but both should be valid Swift dictionary literals + #expect(literal1.contains("1: \"a\"")) + #expect(literal1.contains("2: \"b\"")) + #expect(literal1.contains("3: \"c\"")) + #expect(literal2.contains("1: \"a\"")) + #expect(literal2.contains("2: \"b\"")) + #expect(literal2.contains("3: \"c\"")) + } +} diff --git a/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift b/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift new file mode 100644 index 0000000..b013daa --- /dev/null +++ b/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift @@ -0,0 +1,228 @@ +// +// OptionsMacroIntegrationTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyntaxKit + +struct OptionsMacroIntegrationTests { + // MARK: - Enum with Raw Values (Dictionary) Tests + + @Test func testEnumWithRawValuesCreatesDictionary() { + // Simulate the Options macro expansion for an enum with raw values + let keyValues: [Int: String] = [2: "a", 5: "b", 6: "c", 12: "d"] + + let extensionDecl = Extension("MockDictionaryEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: keyValues).static() + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains( + "extension MockDictionaryEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [Int: String]")) + #expect(generated.contains("2: \"a\"")) + #expect(generated.contains("5: \"b\"")) + #expect(generated.contains("6: \"c\"")) + #expect(generated.contains("12: \"d\"")) + } + + @Test func testEnumWithoutRawValuesCreatesArray() { + // Simulate the Options macro expansion for an enum without raw values + let caseNames: [String] = ["red", "green", "blue"] + + let extensionDecl = Extension("Color") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: caseNames).static() + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension Color: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect( + generated.contains("static let mappedValues: [String] = [\"red\", \"green\", \"blue\"]")) + } + + // MARK: - Complex Integration Tests + + @Test func testCompleteOptionsMacroWorkflow() { + // This test demonstrates the complete workflow that the Options macro would use + + // Step 1: Determine if enum has raw values (simulated) + let hasRawValues = true + let enumName = "TestEnum" + + // Step 2: Create the appropriate mappedValues variable + let mappedValuesVariable: Variable + if hasRawValues { + let keyValues: [Int: String] = [1: "first", 2: "second", 3: "third"] + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues).static() + } else { + let caseNames: [String] = ["first", "second", "third"] + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames).static() + } + + // Step 3: Create the extension + let extensionDecl = Extension(enumName) { + TypeAlias("MappedType", equals: "String") + mappedValuesVariable + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + // Verify the complete extension + #expect( + generated.contains("extension TestEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [Int: String]")) + #expect(generated.contains("1: \"first\"")) + #expect(generated.contains("2: \"second\"")) + #expect(generated.contains("3: \"third\"")) + } + + @Test func testOptionsMacroWorkflowWithoutRawValues() { + // Test the workflow for enums without raw values + + let hasRawValues = false + let enumName = "SimpleEnum" + + let mappedValuesVariable: Variable + if hasRawValues { + let keyValues: [Int: String] = [1: "first", 2: "second"] + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues).static() + } else { + let caseNames: [String] = ["first", "second"] + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames).static() + } + + let extensionDecl = Extension(enumName) { + TypeAlias("MappedType", equals: "String") + mappedValuesVariable + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains("extension SimpleEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [String] = [\"first\", \"second\"]")) + } + + // MARK: - Edge Cases + + @Test func testEmptyEnumCases() { + let caseNames: [String] = [] + + let extensionDecl = Extension("EmptyEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: caseNames).static() + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains("extension EmptyEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [String] = []")) + } + + @Test func testEmptyDictionary() { + let keyValues: [Int: String] = [:] + + let extensionDecl = Extension("EmptyDictEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: keyValues).static() + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains( + "extension EmptyDictEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [Int: String] = []")) + } + + @Test func testSpecialCharactersInCaseNames() { + let caseNames: [String] = ["case_with_underscore", "case-with-dash", "caseWithCamelCase"] + + let extensionDecl = Extension("SpecialEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: caseNames).static() + }.inherits("MappedValueRepresentable", "MappedValueRepresented") + + let generated = extensionDecl.generateCode().normalize() + + #expect( + generated.contains("extension SpecialEnum: MappedValueRepresentable, MappedValueRepresented")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [String]")) + #expect(generated.contains("\"case_with_underscore\"")) + #expect(generated.contains("\"case-with-dash\"")) + #expect(generated.contains("\"caseWithCamelCase\"")) + } + + // MARK: - API Validation Tests + + @Test func testNewSyntaxKitAPICompleteness() { + // Verify that all the new API components work together correctly + + // Test LiteralValue protocol + let array: [String] = ["a", "b", "c"] + #expect(array.typeName == "[String]") + #expect(array.literalString == "[\"a\", \"b\", \"c\"]") + + let dict: [Int: String] = [1: "a", 2: "b"] + #expect(dict.typeName == "[Int: String]") + #expect(dict.literalString.contains("1: \"a\"")) + #expect(dict.literalString.contains("2: \"b\"")) + + // Test Variable with static support + let staticVar = Variable(.let, name: "test", equals: array).static() + let staticGenerated = staticVar.generateCode().normalize() + #expect(staticGenerated.contains("static let test: [String] = [\"a\", \"b\", \"c\"]")) + + // Test Extension with inheritance + let ext = Extension("Test") { + // Empty content + }.inherits("Protocol1", "Protocol2") + + let extGenerated = ext.generateCode().normalize() + #expect(extGenerated.contains("extension Test: Protocol1, Protocol2")) + + // Test TypeAlias + let alias = TypeAlias("MyType", equals: "String") + let aliasGenerated = alias.generateCode().normalize() + #expect(aliasGenerated.contains("typealias MyType = String")) + } +} diff --git a/Tests/SyntaxKitTests/TypeAliasTests.swift b/Tests/SyntaxKitTests/TypeAliasTests.swift new file mode 100644 index 0000000..c67c4eb --- /dev/null +++ b/Tests/SyntaxKitTests/TypeAliasTests.swift @@ -0,0 +1,176 @@ +// +// TypeAliasTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyntaxKit + +struct TypeAliasTests { + // MARK: - Basic TypeAlias Tests + + @Test func testBasicTypeAlias() { + let typeAlias = TypeAlias("MappedType", equals: "String") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias MappedType = String")) + } + + @Test func testTypeAliasWithComplexType() { + let typeAlias = TypeAlias("ResultType", equals: "Result") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias ResultType = Result")) + } + + @Test func testTypeAliasWithGenericType() { + let typeAlias = TypeAlias("ArrayType", equals: "Array") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias ArrayType = Array")) + } + + @Test func testTypeAliasWithOptionalType() { + let typeAlias = TypeAlias("OptionalString", equals: "String?") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias OptionalString = String?")) + } + + // MARK: - TypeAlias in Context Tests + + @Test func testTypeAliasInExtension() { + let extensionDecl = Extension("MyEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "test", type: "MappedType", equals: "value") + } + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension MyEnum")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("let test: MappedType = value")) + } + + @Test func testTypeAliasInStruct() { + let structDecl = Struct("Container") { + TypeAlias("ElementType", equals: "String") + Variable(.let, name: "element", type: "ElementType") + } + + let generated = structDecl.generateCode().normalize() + + #expect(generated.contains("struct Container")) + #expect(generated.contains("typealias ElementType = String")) + #expect(generated.contains("let element: ElementType")) + } + + @Test func testTypeAliasInEnum() { + let enumDecl = Enum("Result") { + TypeAlias("SuccessType", equals: "String") + TypeAlias("FailureType", equals: "Error") + EnumCase("success") + EnumCase("failure") + } + + let generated = enumDecl.generateCode().normalize() + + #expect(generated.contains("enum Result")) + #expect(generated.contains("typealias SuccessType = String")) + #expect(generated.contains("typealias FailureType = Error")) + #expect(generated.contains("case success")) + #expect(generated.contains("case failure")) + } + + // MARK: - Edge Cases + + @Test func testTypeAliasWithSpecialCharacters() { + let typeAlias = TypeAlias("GenericType", equals: "Array") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias GenericType = Array")) + } + + @Test func testTypeAliasWithProtocolComposition() { + let typeAlias = TypeAlias("ProtocolType", equals: "Protocol1 & Protocol2") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias ProtocolType = Protocol1 & Protocol2")) + } + + @Test func testTypeAliasWithFunctionType() { + let typeAlias = TypeAlias("Handler", equals: "(String) -> Void") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias Handler = (String) -> Void")) + } + + @Test func testTypeAliasWithTupleType() { + let typeAlias = TypeAlias("Coordinate", equals: "(x: Double, y: Double)") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias Coordinate = (x: Double, y: Double)")) + } + + @Test func testTypeAliasWithClosureType() { + let typeAlias = TypeAlias("Callback", equals: "@escaping (Result) -> Void") + let generated = typeAlias.generateCode().normalize() + + #expect(generated.contains("typealias Callback = @escaping (Result) -> Void")) + } + + // MARK: - Integration Tests + + @Test func testTypeAliasWithStaticVariable() { + let extensionDecl = Extension("MyEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: ["a", "b", "c"]).static() + }.inherits("MappedValueRepresentable") + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension MyEnum: MappedValueRepresentable")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [String] = [\"a\", \"b\", \"c\"]")) + } + + @Test func testTypeAliasWithDictionaryVariable() { + let extensionDecl = Extension("MyEnum") { + TypeAlias("MappedType", equals: "String") + Variable(.let, name: "mappedValues", equals: [1: "a", 2: "b"]).static() + }.inherits("MappedValueRepresentable") + + let generated = extensionDecl.generateCode().normalize() + + #expect(generated.contains("extension MyEnum: MappedValueRepresentable")) + #expect(generated.contains("typealias MappedType = String")) + #expect(generated.contains("static let mappedValues: [Int: String]")) + #expect(generated.contains("1: \"a\"")) + #expect(generated.contains("2: \"b\"")) + } +} diff --git a/Tests/SyntaxKitTests/VariableStaticTests.swift b/Tests/SyntaxKitTests/VariableStaticTests.swift new file mode 100644 index 0000000..38e1936 --- /dev/null +++ b/Tests/SyntaxKitTests/VariableStaticTests.swift @@ -0,0 +1,154 @@ +// +// VariableStaticTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyntaxKit + +struct VariableStaticTests { + // MARK: - Static Variable Tests + + @Test func testStaticVariableWithStringLiteral() { + let variable = Variable(.let, name: "test", type: "String", equals: "hello").static() + let generated = variable.generateCode().normalize() + + #expect(generated.contains("static let test: String = hello")) + } + + @Test func testStaticVariableWithArrayLiteral() { + let array: [String] = ["a", "b", "c"] + let variable = Variable(.let, name: "mappedValues", equals: array).static() + let generated = variable.generateCode().normalize() + + #expect(generated.contains("static let mappedValues: [String] = [\"a\", \"b\", \"c\"]")) + } + + @Test func testStaticVariableWithDictionaryLiteral() { + let dict: [Int: String] = [1: "a", 2: "b", 3: "c"] + let variable = Variable(.let, name: "mappedValues", equals: dict).static() + let generated = variable.generateCode().normalize() + + #expect(generated.contains("static let mappedValues: [Int: String]")) + #expect(generated.contains("1: \"a\"")) + #expect(generated.contains("2: \"b\"")) + #expect(generated.contains("3: \"c\"")) + } + + @Test func testStaticVariableWithVar() { + let variable = Variable(.var, name: "counter", type: "Int", equals: "0").static() + let generated = variable.generateCode().normalize() + + #expect(generated.contains("static var counter: Int = 0")) + } + + // MARK: - Non-Static Variable Tests + + @Test func testNonStaticVariableWithLiteral() { + let array: [String] = ["x", "y", "z"] + let variable = Variable(.let, name: "values", equals: array) + let generated = variable.generateCode().normalize() + + #expect(generated.contains("let values: [String] = [\"x\", \"y\", \"z\"]")) + #expect(!generated.contains("static")) + } + + @Test func testNonStaticVariableWithDictionary() { + let dict: [Int: String] = [10: "ten", 20: "twenty"] + let variable = Variable(.let, name: "lookup", equals: dict) + let generated = variable.generateCode().normalize() + + #expect(generated.contains("let lookup: [Int: String]")) + #expect(generated.contains("10: \"ten\"")) + #expect(generated.contains("20: \"twenty\"")) + #expect(!generated.contains("static")) + } + + // MARK: - Static Method Tests + + @Test func testStaticMethodReturnsNewInstance() { + let original = Variable(.let, name: "test", type: "String", equals: "value") + let staticVersion = original.static() + + // Should be different instances + #expect(original.generateCode() != staticVersion.generateCode()) + + // Original should not be static + let originalGenerated = original.generateCode().normalize() + #expect(!originalGenerated.contains("static")) + + // Static version should be static + let staticGenerated = staticVersion.generateCode().normalize() + #expect(staticGenerated.contains("static")) + } + + @Test func testStaticMethodPreservesOtherProperties() { + let original = Variable(.var, name: "test", type: "String", equals: "value") + let staticVersion = original.static() + + let originalGenerated = original.generateCode().normalize() + let staticGenerated = staticVersion.generateCode().normalize() + + // Both should have the same name and value + #expect(originalGenerated.contains("test")) + #expect(staticGenerated.contains("test")) + #expect(originalGenerated.contains("value")) + #expect(staticGenerated.contains("value")) + + // Both should be var + #expect(originalGenerated.contains("var")) + #expect(staticGenerated.contains("var")) + } + + // MARK: - Edge Cases + + @Test func testEmptyArrayLiteral() { + let array: [String] = [] + let variable = Variable(.let, name: "empty", equals: array).static() + let generated = variable.generateCode().normalize() + + #expect(generated.contains("static let empty: [String] = []")) + } + + @Test func testEmptyDictionaryLiteral() { + let dict: [Int: String] = [:] + let variable = Variable(.let, name: "empty", equals: dict).static() + let generated = variable.generateCode().normalize() + + #expect(generated.contains("static let empty: [Int: String] = []")) + } + + @Test func testMultipleStaticCalls() { + let variable = Variable(.let, name: "test", type: "String", equals: "value").static().static() + let generated = variable.generateCode().normalize() + + // Should still only have one "static" keyword + let staticCount = generated.components(separatedBy: "static").count - 1 + #expect(staticCount == 1) + } +} diff --git a/project.yml b/project.yml index d39d844..959c793 100644 --- a/project.yml +++ b/project.yml @@ -4,6 +4,10 @@ settings: packages: SyntaxKit: path: . + SKSampleMacro: + path: Macros/SKSampleMacro + Options: + path: Macros/Options aggregateTargets: Lint: buildScripts: From dde37634c092f653a627efefe1a3c4a9b0da98db Mon Sep 17 00:00:00 2001 From: leogdion Date: Wed, 18 Jun 2025 14:13:23 -0400 Subject: [PATCH 02/10] Adding Class and Protocol (#69) * adding Class and Protocol * Add Tests for PR#69 (#71) --------- Co-authored-by: codecov-ai[bot] <156709835+codecov-ai[bot]@users.noreply.github.com> --- Sources/SyntaxKit/Class.swift | 150 ++++++++++++++ .../Documentation.docc/Documentation.md | 8 + Sources/SyntaxKit/FunctionRequirement.swift | 147 ++++++++++++++ Sources/SyntaxKit/PropertyRequirement.swift | 102 ++++++++++ Sources/SyntaxKit/Protocol.swift | 104 ++++++++++ Tests/SyntaxKitTests/ClassTests.swift | 159 +++++++++++++++ Tests/SyntaxKitTests/ProtocolTests.swift | 189 ++++++++++++++++++ 7 files changed, 859 insertions(+) create mode 100644 Sources/SyntaxKit/Class.swift create mode 100644 Sources/SyntaxKit/FunctionRequirement.swift create mode 100644 Sources/SyntaxKit/PropertyRequirement.swift create mode 100644 Sources/SyntaxKit/Protocol.swift create mode 100644 Tests/SyntaxKitTests/ClassTests.swift create mode 100644 Tests/SyntaxKitTests/ProtocolTests.swift diff --git a/Sources/SyntaxKit/Class.swift b/Sources/SyntaxKit/Class.swift new file mode 100644 index 0000000..36d702c --- /dev/null +++ b/Sources/SyntaxKit/Class.swift @@ -0,0 +1,150 @@ +// +// Class.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift `class` declaration. +public struct Class: CodeBlock { + private let name: String + private let members: [CodeBlock] + private var inheritance: [String] = [] + private var genericParameters: [String] = [] + private var isFinal: Bool = false + + /// Creates a `class` declaration. + /// - Parameters: + /// - name: The name of the class. + /// - generics: A list of generic parameters for the class. + /// - content: A ``CodeBlockBuilder`` that provides the members of the class. + public init( + _ name: String, + generics: [String] = [], + @CodeBlockBuilderResult _ content: () -> [CodeBlock] + ) { + self.name = name + self.members = content() + self.genericParameters = generics + } + + /// Sets one or more inherited types (superclass first followed by any protocols). + /// - Parameter types: The list of types to inherit from. + /// - Returns: A copy of the class with the inheritance set. + public func inherits(_ types: String...) -> Self { + var copy = self + copy.inheritance = types + return copy + } + + /// Marks the class declaration as `final`. + /// - Returns: A copy of the class marked as `final`. + public func final() -> Self { + var copy = self + copy.isFinal = true + return copy + } + + public var syntax: SyntaxProtocol { + let classKeyword = TokenSyntax.keyword(.class, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name) + + // Generic parameter clause + var genericParameterClause: GenericParameterClauseSyntax? + if !genericParameters.isEmpty { + let parameterList = GenericParameterListSyntax( + genericParameters.enumerated().map { idx, name in + var param = GenericParameterSyntax(name: .identifier(name)) + if idx < genericParameters.count - 1 { + param = param.with( + \.trailingComma, + TokenSyntax.commaToken(trailingTrivia: .space) + ) + } + return param + } + ) + genericParameterClause = GenericParameterClauseSyntax( + leftAngle: .leftAngleToken(), + parameters: parameterList, + rightAngle: .rightAngleToken() + ) + } + + // Inheritance clause + var inheritanceClause: InheritanceClauseSyntax? + if !inheritance.isEmpty { + let inheritedTypes = inheritance.map { type in + InheritedTypeSyntax(type: IdentifierTypeSyntax(name: .identifier(type))) + } + inheritanceClause = InheritanceClauseSyntax( + colon: .colonToken(), + inheritedTypes: InheritedTypeListSyntax( + inheritedTypes.enumerated().map { idx, inherited in + var inheritedType = inherited + if idx < inheritedTypes.count - 1 { + inheritedType = inheritedType.with( + \.trailingComma, + TokenSyntax.commaToken(trailingTrivia: .space) + ) + } + return inheritedType + } + ) + ) + } + + // Member block + let memberBlock = MemberBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + members: MemberBlockItemListSyntax( + members.compactMap { member in + guard let decl = member.syntax.as(DeclSyntax.self) else { return nil } + return MemberBlockItemSyntax(decl: decl, trailingTrivia: .newline) + } + ), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + // Modifiers + var modifiers: DeclModifierListSyntax = [] + if isFinal { + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(.final, trailingTrivia: .space)) + ]) + } + + return ClassDeclSyntax( + modifiers: modifiers, + classKeyword: classKeyword, + name: identifier, + genericParameterClause: genericParameterClause, + inheritanceClause: inheritanceClause, + memberBlock: memberBlock + ) + } +} diff --git a/Sources/SyntaxKit/Documentation.docc/Documentation.md b/Sources/SyntaxKit/Documentation.docc/Documentation.md index 091cbee..cb4a2ca 100644 --- a/Sources/SyntaxKit/Documentation.docc/Documentation.md +++ b/Sources/SyntaxKit/Documentation.docc/Documentation.md @@ -198,6 +198,14 @@ struct BlackjackCard { - ``VariableDecl`` - ``Let`` - ``Variable`` +- ``Extension`` +- ``Class`` +- ``Protocol`` +- ``Tuple`` +- ``TypeAlias`` +- ``Infix`` +- ``PropertyRequirement`` +- ``FunctionRequirement`` ### Expressions & Statements - ``Assignment`` diff --git a/Sources/SyntaxKit/FunctionRequirement.swift b/Sources/SyntaxKit/FunctionRequirement.swift new file mode 100644 index 0000000..3faf7ae --- /dev/null +++ b/Sources/SyntaxKit/FunctionRequirement.swift @@ -0,0 +1,147 @@ +// +// FunctionRequirement.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A function requirement within a protocol declaration (no body). +public struct FunctionRequirement: CodeBlock { + private let name: String + private let parameters: [Parameter] + private let returnType: String? + private var isStatic: Bool = false + private var isMutating: Bool = false + + /// Creates a parameterless function requirement. + /// - Parameters: + /// - name: The function name. + /// - returnType: Optional return type. + public init(_ name: String, returns returnType: String? = nil) { + self.name = name + self.parameters = [] + self.returnType = returnType + } + + /// Creates a function requirement with parameters. + /// - Parameters: + /// - name: The function name. + /// - returnType: Optional return type. + /// - params: A ParameterBuilderResult providing the parameters. + public init( + _ name: String, returns returnType: String? = nil, + @ParameterBuilderResult _ params: () -> [Parameter] + ) { + self.name = name + self.parameters = params() + self.returnType = returnType + } + + /// Marks the function requirement as `static`. + public func `static`() -> Self { + var copy = self + copy.isStatic = true + return copy + } + + /// Marks the function requirement as `mutating`. + public func mutating() -> Self { + var copy = self + copy.isMutating = true + return copy + } + + public var syntax: SyntaxProtocol { + let funcKeyword = TokenSyntax.keyword(.func, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name) + + // Parameters + let paramList: FunctionParameterListSyntax + if parameters.isEmpty { + paramList = FunctionParameterListSyntax([]) + } else { + paramList = FunctionParameterListSyntax( + parameters.enumerated().compactMap { index, param in + guard !param.name.isEmpty, !param.type.isEmpty else { return nil } + var paramSyntax = FunctionParameterSyntax( + firstName: param.isUnnamed + ? .wildcardToken(trailingTrivia: .space) : .identifier(param.name), + secondName: param.isUnnamed ? .identifier(param.name) : nil, + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(param.type)), + defaultValue: param.defaultValue.map { + InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier($0))) + ) + } + ) + if index < parameters.count - 1 { + paramSyntax = paramSyntax.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return paramSyntax + }) + } + + // Return clause + var returnClause: ReturnClauseSyntax? + if let returnType = returnType { + returnClause = ReturnClauseSyntax( + arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(returnType)) + ) + } + + // Modifiers + var modifiers: DeclModifierListSyntax = [] + if isStatic { + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) + ]) + } + if isMutating { + modifiers = DeclModifierListSyntax( + modifiers + [DeclModifierSyntax(name: .keyword(.mutating, trailingTrivia: .space))] + ) + } + + return FunctionDeclSyntax( + attributes: AttributeListSyntax([]), + modifiers: modifiers, + funcKeyword: funcKeyword, + name: identifier, + signature: FunctionSignatureSyntax( + parameterClause: FunctionParameterClauseSyntax( + leftParen: .leftParenToken(), parameters: paramList, rightParen: .rightParenToken() + ), + effectSpecifiers: nil, + returnClause: returnClause + ), + body: nil + ) + } +} diff --git a/Sources/SyntaxKit/PropertyRequirement.swift b/Sources/SyntaxKit/PropertyRequirement.swift new file mode 100644 index 0000000..0a41fb1 --- /dev/null +++ b/Sources/SyntaxKit/PropertyRequirement.swift @@ -0,0 +1,102 @@ +// +// PropertyRequirement.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A property requirement inside a protocol declaration. +public struct PropertyRequirement: CodeBlock { + /// The accessor options for the property. + public enum Access { + case get + case getSet + } + + private let name: String + private let type: String + private let access: Access + + /// Creates a property requirement. + /// - Parameters: + /// - name: The property name. + /// - type: The property type. + /// - access: Whether the property is get-only or get/set. + public init(_ name: String, type: String, access: Access = .get) { + self.name = name + self.type = type + self.access = access + } + + public var syntax: SyntaxProtocol { + let varKeyword = TokenSyntax.keyword(.var, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) + + let typeAnnotation = TypeAnnotationSyntax( + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(type)) + ) + + // Build accessor list + let accessorList: AccessorDeclListSyntax = { + switch access { + case .get: + return AccessorDeclListSyntax([ + AccessorDeclSyntax( + accessorSpecifier: .keyword(.get, trailingTrivia: .space) + ) + ]) + case .getSet: + return AccessorDeclListSyntax([ + AccessorDeclSyntax( + accessorSpecifier: .keyword(.get, trailingTrivia: .space) + ), + AccessorDeclSyntax( + accessorSpecifier: .keyword(.set, trailingTrivia: .space) + ), + ]) + } + }() + + let accessorBlock = AccessorBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .space), + accessors: .accessors(accessorList), + rightBrace: .rightBraceToken(leadingTrivia: .space, trailingTrivia: .newline) + ) + + return VariableDeclSyntax( + bindingSpecifier: varKeyword, + bindings: PatternBindingListSyntax([ + PatternBindingSyntax( + pattern: IdentifierPatternSyntax(identifier: identifier), + typeAnnotation: typeAnnotation, + accessorBlock: accessorBlock + ) + ]) + ) + } +} diff --git a/Sources/SyntaxKit/Protocol.swift b/Sources/SyntaxKit/Protocol.swift new file mode 100644 index 0000000..71945a8 --- /dev/null +++ b/Sources/SyntaxKit/Protocol.swift @@ -0,0 +1,104 @@ +// +// Protocol.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift `protocol` declaration. +public struct Protocol: CodeBlock { + private let name: String + private let members: [CodeBlock] + private var inheritance: [String] = [] + + /// Creates a `protocol` declaration. + /// - Parameters: + /// - name: The name of the protocol. + /// - content: A ``CodeBlockBuilder`` that provides the members of the protocol. + public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.name = name + self.members = content() + } + + /// Sets one or more inherited protocols. + /// - Parameter types: The list of protocols this protocol inherits from. + /// - Returns: A copy of the protocol with the inheritance set. + public func inherits(_ types: String...) -> Self { + var copy = self + copy.inheritance = types + return copy + } + + public var syntax: SyntaxProtocol { + let protocolKeyword = TokenSyntax.keyword(.protocol, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name) + + // Inheritance clause + var inheritanceClause: InheritanceClauseSyntax? + if !inheritance.isEmpty { + let inheritedTypes = inheritance.map { type in + InheritedTypeSyntax(type: IdentifierTypeSyntax(name: .identifier(type))) + } + inheritanceClause = InheritanceClauseSyntax( + colon: .colonToken(), + inheritedTypes: InheritedTypeListSyntax( + inheritedTypes.enumerated().map { idx, inherited in + var inheritedType = inherited + if idx < inheritedTypes.count - 1 { + inheritedType = inheritedType.with( + \.trailingComma, + TokenSyntax.commaToken(trailingTrivia: .space) + ) + } + return inheritedType + } + ) + ) + } + + // Member block + let memberBlock = MemberBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + members: MemberBlockItemListSyntax( + members.compactMap { member in + guard let decl = member.syntax.as(DeclSyntax.self) else { return nil } + return MemberBlockItemSyntax(decl: decl, trailingTrivia: .newline) + } + ), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + return ProtocolDeclSyntax( + protocolKeyword: protocolKeyword, + name: identifier, + primaryAssociatedTypeClause: nil, + inheritanceClause: inheritanceClause, + genericWhereClause: nil, + memberBlock: memberBlock + ) + } +} diff --git a/Tests/SyntaxKitTests/ClassTests.swift b/Tests/SyntaxKitTests/ClassTests.swift new file mode 100644 index 0000000..f9c3836 --- /dev/null +++ b/Tests/SyntaxKitTests/ClassTests.swift @@ -0,0 +1,159 @@ +import Testing + +@testable import SyntaxKit + +struct ClassTests { + @Test func testClassWithInheritance() { + let carClass = Class("Car") { + Variable(.var, name: "brand", type: "String") + Variable(.var, name: "numberOfWheels", type: "Int") + }.inherits("Vehicle") + + let expected = """ + class Car: Vehicle { + var brand: String + var numberOfWheels: Int + } + """ + + let normalizedGenerated = carClass.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testEmptyClass() { + let emptyClass = Class("EmptyClass") {} + + let expected = """ + class EmptyClass { + } + """ + + let normalizedGenerated = emptyClass.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testClassWithGenerics() { + let genericClass = Class("Container", generics: ["T"]) { + Variable(.var, name: "value", type: "T") + } + + let expected = """ + class Container { + var value: T + } + """ + + let normalizedGenerated = genericClass.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testClassWithMultipleGenerics() { + let multiGenericClass = Class("Pair", generics: ["T", "U"]) { + Variable(.var, name: "first", type: "T") + Variable(.var, name: "second", type: "U") + } + + let expected = """ + class Pair { + var first: T + var second: U + } + """ + + let normalizedGenerated = multiGenericClass.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testFinalClass() { + let finalClass = Class("FinalClass") { + Variable(.var, name: "value", type: "String") + }.final() + + let expected = """ + final class FinalClass { + var value: String + } + """ + + let normalizedGenerated = finalClass.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testClassWithMultipleInheritance() { + let classWithMultipleInheritance = Class("AdvancedVehicle") { + Variable(.var, name: "speed", type: "Int") + }.inherits("Vehicle", "Codable", "Equatable") + + let expected = """ + class AdvancedVehicle: Vehicle, Codable, Equatable { + var speed: Int + } + """ + + let normalizedGenerated = classWithMultipleInheritance.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testClassWithGenericsAndInheritance() { + let genericClassWithInheritance = Class("GenericContainer", generics: ["T"]) { + Variable(.var, name: "items", type: "[T]") + }.inherits("Collection") + + let expected = """ + class GenericContainer: Collection { + var items: [T] + } + """ + + let normalizedGenerated = genericClassWithInheritance.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testFinalClassWithInheritanceAndGenerics() { + let finalGenericClass = Class("FinalGenericClass", generics: ["T"]) { + Variable(.var, name: "value", type: "T") + }.inherits("BaseClass").final() + + let expected = """ + final class FinalGenericClass: BaseClass { + var value: T + } + """ + + let normalizedGenerated = finalGenericClass.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testClassWithFunctions() { + let classWithFunctions = Class("Calculator") { + Function("add", returns: "Int") { + Parameter(name: "a", type: "Int") + Parameter(name: "b", type: "Int") + } _: { + Return { + VariableExp("a + b") + } + } + } + + let expected = """ + class Calculator { + func add(a: Int, b: Int) -> Int { + return a + b + } + } + """ + + let normalizedGenerated = classWithFunctions.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } +} diff --git a/Tests/SyntaxKitTests/ProtocolTests.swift b/Tests/SyntaxKitTests/ProtocolTests.swift new file mode 100644 index 0000000..31a3c55 --- /dev/null +++ b/Tests/SyntaxKitTests/ProtocolTests.swift @@ -0,0 +1,189 @@ +import Testing + +@testable import SyntaxKit + +struct ProtocolTests { + @Test func testSimpleProtocol() { + let vehicleProtocol = Protocol("Vehicle") { + PropertyRequirement("numberOfWheels", type: "Int", access: .get) + PropertyRequirement("brand", type: "String", access: .getSet) + FunctionRequirement("start") + FunctionRequirement("stop") + FunctionRequirement("speed", returns: "Int") + } + + let expected = """ + protocol Vehicle { + var numberOfWheels: Int { get } + var brand: String { get set } + func start() + func stop() + func speed() -> Int + } + """ + + let normalizedGenerated = vehicleProtocol.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testEmptyProtocol() { + let emptyProtocol = Protocol("EmptyProtocol") {} + + let expected = """ + protocol EmptyProtocol { + } + """ + + let normalizedGenerated = emptyProtocol.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testProtocolWithInheritance() { + let protocolWithInheritance = Protocol("MyProtocol") { + PropertyRequirement("value", type: "String", access: .getSet) + }.inherits("Equatable", "Hashable") + + let expected = """ + protocol MyProtocol: Equatable, Hashable { + var value: String { get set } + } + """ + + let normalizedGenerated = protocolWithInheritance.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testFunctionRequirementWithParameters() { + let protocolWithFunction = Protocol("Calculator") { + FunctionRequirement("add", returns: "Int") { + Parameter(name: "a", type: "Int") + Parameter(name: "b", type: "Int") + } + } + + let expected = """ + protocol Calculator { + func add(a: Int, b: Int) -> Int + } + """ + + let normalizedGenerated = protocolWithFunction.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testStaticFunctionRequirement() { + let protocolWithStaticFunction = Protocol("Factory") { + FunctionRequirement("create", returns: "Self").static() + } + + let expected = """ + protocol Factory { + static func create() -> Self + } + """ + + let normalizedGenerated = protocolWithStaticFunction.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testMutatingFunctionRequirement() { + let protocolWithMutatingFunction = Protocol("Resettable") { + FunctionRequirement("reset").mutating() + } + + let expected = """ + protocol Resettable { + mutating func reset() + } + """ + + let normalizedGenerated = protocolWithMutatingFunction.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testPropertyRequirementGetOnly() { + let propertyReq = PropertyRequirement("readOnlyProperty", type: "String", access: .get) + let prtcl = Protocol("TestProtocol") { + propertyReq + } + + let expected = """ + protocol TestProtocol { + var readOnlyProperty: String { get } + } + """ + + let normalizedGenerated = prtcl.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testPropertyRequirementGetSet() { + let propertyReq = PropertyRequirement("readWriteProperty", type: "Int", access: .getSet) + let prtcl = Protocol("TestProtocol") { + propertyReq + } + + let expected = """ + protocol TestProtocol { + var readWriteProperty: Int { get set } + } + """ + + let normalizedGenerated = prtcl.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testFunctionRequirementWithDefaultParameters() { + let functionReq = FunctionRequirement("process", returns: "String") { + Parameter(name: "input", type: "String") + Parameter(name: "options", type: "ProcessingOptions", defaultValue: "ProcessingOptions()") + } + let prtcl = Protocol("TestProtocol") { + functionReq + } + + let expected = """ + protocol TestProtocol { + func process(input: String, options: ProcessingOptions = ProcessingOptions()) -> String + } + """ + + let normalizedGenerated = prtcl.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } + + @Test func testComplexProtocolWithMixedRequirements() { + let complexProtocol = Protocol("ComplexProtocol") { + PropertyRequirement("id", type: "UUID", access: .get) + PropertyRequirement("name", type: "String", access: .getSet) + FunctionRequirement("initialize").mutating() + FunctionRequirement("process", returns: "Result") { + Parameter(name: "input", type: "Data") + } + FunctionRequirement("factory", returns: "Self").static() + }.inherits("Identifiable") + + let expected = """ + protocol ComplexProtocol: Identifiable { + var id: UUID { get } + var name: String { get set } + mutating func initialize() + func process(input: Data) -> Result + static func factory() -> Self + } + """ + + let normalizedGenerated = complexProtocol.generateCode().normalize() + let normalizedExpected = expected.normalize() + #expect(normalizedGenerated == normalizedExpected) + } +} From ed9de3965b2c7c3d6945cbfdf19abd4fce6e0df3 Mon Sep 17 00:00:00 2001 From: leogdion Date: Wed, 18 Jun 2025 16:40:12 -0400 Subject: [PATCH 03/10] Adding Attributes (#72) --- Examples/Remaining/attributes/code.swift | 14 ++ Examples/Remaining/attributes/dsl.swift | 7 + Examples/Remaining/attributes/syntax.json | 0 Sources/SyntaxKit/Attribute.swift | 100 +++++++++++ Sources/SyntaxKit/Class.swift | 88 ++++++++-- Sources/SyntaxKit/Enum.swift | 58 +++++++ Sources/SyntaxKit/Extension.swift | 66 ++++++- Sources/SyntaxKit/Function.swift | 74 +++++++- Sources/SyntaxKit/Parameter.swift | 13 ++ Sources/SyntaxKit/Protocol.swift | 58 +++++++ Sources/SyntaxKit/Struct.swift | 81 ++++++++- Sources/SyntaxKit/TypeAlias.swift | 58 +++++++ Sources/SyntaxKit/Variable.swift | 60 +++++++ Tests/SyntaxKitTests/AttributeTests.swift | 199 ++++++++++++++++++++++ Tests/SyntaxKitTests/ClassTests.swift | 20 +-- Tests/SyntaxKitTests/StructTests.swift | 8 +- 16 files changed, 863 insertions(+), 41 deletions(-) create mode 100644 Examples/Remaining/attributes/code.swift create mode 100644 Examples/Remaining/attributes/dsl.swift create mode 100644 Examples/Remaining/attributes/syntax.json create mode 100644 Sources/SyntaxKit/Attribute.swift create mode 100644 Tests/SyntaxKitTests/AttributeTests.swift diff --git a/Examples/Remaining/attributes/code.swift b/Examples/Remaining/attributes/code.swift new file mode 100644 index 0000000..5e5e708 --- /dev/null +++ b/Examples/Remaining/attributes/code.swift @@ -0,0 +1,14 @@ +@objc +class Foo { + @Published var bar: String = "bar" + + @available(iOS 17.0, *) + func bar() { + print("bar") + } + + @MainActor + func baz() { + print("baz") + } +} \ No newline at end of file diff --git a/Examples/Remaining/attributes/dsl.swift b/Examples/Remaining/attributes/dsl.swift new file mode 100644 index 0000000..daf5416 --- /dev/null +++ b/Examples/Remaining/attributes/dsl.swift @@ -0,0 +1,7 @@ +Class("Foo") { + Variable(.var, name: "bar", type: "String", defaultValue: "bar").attribute("Published") + Function("bar") { + print("bar") + }.attribute("available", arguments: ["iOS 17.0", "*"]) + Function("baz") { +}.attribute("objc")}.attribute("objc") \ No newline at end of file diff --git a/Examples/Remaining/attributes/syntax.json b/Examples/Remaining/attributes/syntax.json new file mode 100644 index 0000000..e69de29 diff --git a/Sources/SyntaxKit/Attribute.swift b/Sources/SyntaxKit/Attribute.swift new file mode 100644 index 0000000..c3d909b --- /dev/null +++ b/Sources/SyntaxKit/Attribute.swift @@ -0,0 +1,100 @@ +// +// Attribute.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Internal representation of a Swift attribute with its arguments. +internal struct AttributeInfo { + let name: String + let arguments: [String] + + init(name: String, arguments: [String] = []) { + self.name = name + self.arguments = arguments + } +} + +/// A Swift attribute that can be used as a property wrapper. +public struct Attribute: CodeBlock { + private let name: String + private let arguments: [String] + + /// Creates an attribute with the given name and optional arguments. + /// - Parameters: + /// - name: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + public init(_ name: String, arguments: [String] = []) { + self.name = name + self.arguments = arguments + } + + /// Creates an attribute with a name and a single argument. + /// - Parameters: + /// - name: The name of the attribute (without the @ symbol). + /// - argument: The argument for the attribute. + public init(_ name: String, argument: String) { + self.name = name + self.arguments = [argument] + } + + public var syntax: SyntaxProtocol { + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + } +} diff --git a/Sources/SyntaxKit/Class.swift b/Sources/SyntaxKit/Class.swift index 36d702c..2c11da2 100644 --- a/Sources/SyntaxKit/Class.swift +++ b/Sources/SyntaxKit/Class.swift @@ -36,28 +36,32 @@ public struct Class: CodeBlock { private var inheritance: [String] = [] private var genericParameters: [String] = [] private var isFinal: Bool = false + private var attributes: [AttributeInfo] = [] /// Creates a `class` declaration. /// - Parameters: /// - name: The name of the class. - /// - generics: A list of generic parameters for the class. /// - content: A ``CodeBlockBuilder`` that provides the members of the class. - public init( - _ name: String, - generics: [String] = [], - @CodeBlockBuilderResult _ content: () -> [CodeBlock] - ) { + public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { self.name = name self.members = content() - self.genericParameters = generics } - /// Sets one or more inherited types (superclass first followed by any protocols). - /// - Parameter types: The list of types to inherit from. + /// Sets the generic parameters for the class. + /// - Parameter generics: The list of generic parameter names. + /// - Returns: A copy of the class with the generic parameters set. + public func generic(_ generics: String...) -> Self { + var copy = self + copy.genericParameters = generics + return copy + } + + /// Sets the inheritance for the class. + /// - Parameter type: The type to inherit from. /// - Returns: A copy of the class with the inheritance set. - public func inherits(_ types: String...) -> Self { + public func inherits(_ type: String) -> Self { var copy = self - copy.inheritance = types + copy.inheritance = [type] return copy } @@ -69,10 +73,24 @@ public struct Class: CodeBlock { return copy } + /// Adds an attribute to the class declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the class with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { let classKeyword = TokenSyntax.keyword(.class, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name) + // Build attributes + let attributeList = buildAttributeList(from: attributes) + // Generic parameter clause var genericParameterClause: GenericParameterClauseSyntax? if !genericParameters.isEmpty { @@ -139,6 +157,7 @@ public struct Class: CodeBlock { } return ClassDeclSyntax( + attributes: attributeList, modifiers: modifiers, classKeyword: classKeyword, name: identifier, @@ -147,4 +166,51 @@ public struct Class: CodeBlock { memberBlock: memberBlock ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + + let attributeElements = attributes.map { attribute in + let arguments = attribute.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attribute.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + + return AttributeListSyntax(attributeElements) + } } diff --git a/Sources/SyntaxKit/Enum.swift b/Sources/SyntaxKit/Enum.swift index 170f78b..82e6dd4 100644 --- a/Sources/SyntaxKit/Enum.swift +++ b/Sources/SyntaxKit/Enum.swift @@ -34,6 +34,7 @@ public struct Enum: CodeBlock { private let name: String private let members: [CodeBlock] private var inheritance: String? + private var attributes: [AttributeInfo] = [] /// Creates an `enum` declaration. /// - Parameters: @@ -53,6 +54,17 @@ public struct Enum: CodeBlock { return copy } + /// Adds an attribute to the enum declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the enum with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { let enumKeyword = TokenSyntax.keyword(.enum, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) @@ -76,12 +88,58 @@ public struct Enum: CodeBlock { ) return EnumDeclSyntax( + attributes: buildAttributeList(from: attributes), enumKeyword: enumKeyword, name: identifier, inheritanceClause: inheritanceClause, memberBlock: memberBlock ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + return AttributeListSyntax(attributeElements) + } } /// A Swift `case` declaration inside an `enum`. diff --git a/Sources/SyntaxKit/Extension.swift b/Sources/SyntaxKit/Extension.swift index 522c5fc..a61f803 100644 --- a/Sources/SyntaxKit/Extension.swift +++ b/Sources/SyntaxKit/Extension.swift @@ -34,18 +34,19 @@ public struct Extension: CodeBlock { private let extendedType: String private let members: [CodeBlock] private var inheritance: [String] = [] + private var attributes: [AttributeInfo] = [] - /// Creates an `extension` declaration. + /// Creates an extension declaration. /// - Parameters: - /// - extendedType: The name of the type being extended. + /// - extendedType: The type being extended. /// - content: A ``CodeBlockBuilder`` that provides the members of the extension. public init(_ extendedType: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { self.extendedType = extendedType self.members = content() } - /// Sets the inheritance for the extension. - /// - Parameter types: The types to inherit from. + /// Sets one or more inherited protocols. + /// - Parameter types: The list of protocols this extension conforms to. /// - Returns: A copy of the extension with the inheritance set. public func inherits(_ types: String...) -> Self { var copy = self @@ -53,6 +54,17 @@ public struct Extension: CodeBlock { return copy } + /// Adds an attribute to the extension declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the extension with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { let extensionKeyword = TokenSyntax.keyword(.extension, trailingTrivia: .space) let identifier = TokenSyntax.identifier(extendedType, trailingTrivia: .space) @@ -87,10 +99,56 @@ public struct Extension: CodeBlock { ) return ExtensionDeclSyntax( + attributes: buildAttributeList(from: attributes), extensionKeyword: extensionKeyword, extendedType: IdentifierTypeSyntax(name: identifier), inheritanceClause: inheritanceClause, memberBlock: memberBlock ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.map { attribute in + let arguments = attribute.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attribute.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + return AttributeListSyntax(attributeElements) + } } diff --git a/Sources/SyntaxKit/Function.swift b/Sources/SyntaxKit/Function.swift index bac906f..8afa892 100644 --- a/Sources/SyntaxKit/Function.swift +++ b/Sources/SyntaxKit/Function.swift @@ -37,6 +37,7 @@ public struct Function: CodeBlock { private let body: [CodeBlock] private var isStatic: Bool = false private var isMutating: Bool = false + private var attributes: [AttributeInfo] = [] /// Creates a `func` declaration. /// - Parameters: @@ -86,6 +87,17 @@ public struct Function: CodeBlock { return copy } + /// Adds an attribute to the function declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the function with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { let funcKeyword = TokenSyntax.keyword(.func, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name) @@ -98,11 +110,20 @@ public struct Function: CodeBlock { paramList = FunctionParameterListSyntax( parameters.enumerated().compactMap { index, param in guard !param.name.isEmpty, !param.type.isEmpty else { return nil } + + // Build parameter attributes + let paramAttributes = buildAttributeList(from: param.attributes) + + // Determine spacing for firstName based on whether attributes are present + let firstNameLeadingTrivia: Trivia = paramAttributes.isEmpty ? [] : .space + var paramSyntax = FunctionParameterSyntax( + attributes: paramAttributes, firstName: param.isUnnamed - ? .wildcardToken(trailingTrivia: .space) : .identifier(param.name), + ? .wildcardToken(leadingTrivia: firstNameLeadingTrivia, trailingTrivia: .space) + : .identifier(param.name, leadingTrivia: firstNameLeadingTrivia), secondName: param.isUnnamed ? .identifier(param.name) : nil, - colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + colon: .colonToken(trailingTrivia: .space), type: IdentifierTypeSyntax(name: .identifier(param.type)), defaultValue: param.defaultValue.map { InitializerClauseSyntax( @@ -160,7 +181,7 @@ public struct Function: CodeBlock { } return FunctionDeclSyntax( - attributes: AttributeListSyntax([]), + attributes: buildAttributeList(from: attributes), modifiers: modifiers, funcKeyword: funcKeyword, name: identifier, @@ -178,4 +199,51 @@ public struct Function: CodeBlock { body: bodyBlock ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + + return AttributeListSyntax(attributeElements) + } } diff --git a/Sources/SyntaxKit/Parameter.swift b/Sources/SyntaxKit/Parameter.swift index 08c76d9..75703c2 100644 --- a/Sources/SyntaxKit/Parameter.swift +++ b/Sources/SyntaxKit/Parameter.swift @@ -37,6 +37,7 @@ public struct Parameter: CodeBlock { let type: String let defaultValue: String? let isUnnamed: Bool + internal var attributes: [AttributeInfo] = [] /// Creates a parameter for a function or initializer. /// - Parameters: @@ -51,6 +52,17 @@ public struct Parameter: CodeBlock { self.isUnnamed = isUnnamed } + /// Adds an attribute to the parameter declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the parameter with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { // Not used for function signature, but for call sites (Init, etc.) if let defaultValue = defaultValue { @@ -66,5 +78,6 @@ public struct Parameter: CodeBlock { expression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) ) } + // Note: If you want to support attributes in parameter syntax, you would need to update the function signature generation in Function.swift to use these attributes. } } diff --git a/Sources/SyntaxKit/Protocol.swift b/Sources/SyntaxKit/Protocol.swift index 71945a8..bc11002 100644 --- a/Sources/SyntaxKit/Protocol.swift +++ b/Sources/SyntaxKit/Protocol.swift @@ -34,6 +34,7 @@ public struct Protocol: CodeBlock { private let name: String private let members: [CodeBlock] private var inheritance: [String] = [] + private var attributes: [AttributeInfo] = [] /// Creates a `protocol` declaration. /// - Parameters: @@ -53,6 +54,17 @@ public struct Protocol: CodeBlock { return copy } + /// Adds an attribute to the protocol declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the protocol with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { let protocolKeyword = TokenSyntax.keyword(.protocol, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name) @@ -93,6 +105,7 @@ public struct Protocol: CodeBlock { ) return ProtocolDeclSyntax( + attributes: buildAttributeList(from: attributes), protocolKeyword: protocolKeyword, name: identifier, primaryAssociatedTypeClause: nil, @@ -101,4 +114,49 @@ public struct Protocol: CodeBlock { memberBlock: memberBlock ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + return AttributeListSyntax(attributeElements) + } } diff --git a/Sources/SyntaxKit/Struct.swift b/Sources/SyntaxKit/Struct.swift index 50d6dc6..48e95ce 100644 --- a/Sources/SyntaxKit/Struct.swift +++ b/Sources/SyntaxKit/Struct.swift @@ -33,28 +33,45 @@ import SwiftSyntax public struct Struct: CodeBlock { private let name: String private let members: [CodeBlock] - private var inheritance: String? private var genericParameter: String? + private var inheritance: String? + private var attributes: [AttributeInfo] = [] /// Creates a `struct` declaration. /// - Parameters: /// - name: The name of the struct. - /// - generic: A generic parameter for the struct, if any. /// - content: A ``CodeBlockBuilder`` that provides the members of the struct. - public init( - _ name: String, generic: String? = nil, @CodeBlockBuilderResult _ content: () -> [CodeBlock] - ) { + public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { self.name = name self.members = content() - self.genericParameter = generic + } + + /// Sets the generic parameter for the struct. + /// - Parameter generic: The generic parameter name. + /// - Returns: A copy of the struct with the generic parameter set. + public func generic(_ generic: String) -> Self { + var copy = self + copy.genericParameter = generic + return copy } /// Sets the inheritance for the struct. - /// - Parameter type: The type to inherit from. + /// - Parameter inheritance: The type to inherit from. /// - Returns: A copy of the struct with the inheritance set. - public func inherits(_ type: String) -> Self { + public func inherits(_ inheritance: String) -> Self { + var copy = self + copy.inheritance = inheritance + return copy + } + + /// Adds an attribute to the struct declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the struct with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { var copy = self - copy.inheritance = type + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) return copy } @@ -94,6 +111,7 @@ public struct Struct: CodeBlock { ) return StructDeclSyntax( + attributes: buildAttributeList(from: attributes), structKeyword: structKeyword, name: identifier, genericParameterClause: genericParameterClause, @@ -101,4 +119,49 @@ public struct Struct: CodeBlock { memberBlock: memberBlock ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + return AttributeListSyntax(attributeElements) + } } diff --git a/Sources/SyntaxKit/TypeAlias.swift b/Sources/SyntaxKit/TypeAlias.swift index 7f8672b..90b17e0 100644 --- a/Sources/SyntaxKit/TypeAlias.swift +++ b/Sources/SyntaxKit/TypeAlias.swift @@ -33,6 +33,7 @@ import SwiftSyntax public struct TypeAlias: CodeBlock { private let name: String private let existingType: String + private var attributes: [AttributeInfo] = [] /// Creates a `typealias` declaration. /// - Parameters: @@ -43,6 +44,17 @@ public struct TypeAlias: CodeBlock { self.existingType = type } + /// Adds an attribute to the typealias declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the typealias with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { // `typealias` keyword token let keyword = TokenSyntax.keyword(.typealias, trailingTrivia: .space) @@ -57,9 +69,55 @@ public struct TypeAlias: CodeBlock { ) return TypeAliasDeclSyntax( + attributes: buildAttributeList(from: attributes), typealiasKeyword: keyword, name: identifier, initializer: initializer ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + return AttributeListSyntax(attributeElements) + } } diff --git a/Sources/SyntaxKit/Variable.swift b/Sources/SyntaxKit/Variable.swift index 40140ba..cf3f044 100644 --- a/Sources/SyntaxKit/Variable.swift +++ b/Sources/SyntaxKit/Variable.swift @@ -36,6 +36,7 @@ public struct Variable: CodeBlock { private let type: String private let defaultValue: String? private var isStatic: Bool = false + private var attributes: [AttributeInfo] = [] /// Creates a `let` or `var` declaration with an explicit type. /// - Parameters: @@ -71,6 +72,17 @@ public struct Variable: CodeBlock { return copy } + /// Adds an attribute to the variable declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the variable with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + public var syntax: SyntaxProtocol { let bindingKeyword = TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) @@ -94,6 +106,7 @@ public struct Variable: CodeBlock { } return VariableDeclSyntax( + attributes: buildAttributeList(from: attributes), modifiers: modifiers, bindingSpecifier: bindingKeyword, bindings: PatternBindingListSyntax([ @@ -105,4 +118,51 @@ public struct Variable: CodeBlock { ]) ) } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + + return AttributeListSyntax(attributeElements) + } } diff --git a/Tests/SyntaxKitTests/AttributeTests.swift b/Tests/SyntaxKitTests/AttributeTests.swift new file mode 100644 index 0000000..717811a --- /dev/null +++ b/Tests/SyntaxKitTests/AttributeTests.swift @@ -0,0 +1,199 @@ +// +// AttributeTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SyntaxKit +import Testing + +@Suite struct AttributeTests { + @Test("Class with attribute generates correct syntax") + func testClassWithAttribute() throws { + let classDecl = Class("Foo") { + Variable(.var, name: "bar", type: "String", equals: "bar") + }.attribute("objc") + + let generated = classDecl.syntax.description + #expect(generated.contains("@objc")) + #expect(generated.contains("class Foo")) + } + + @Test("Function with attribute generates correct syntax") + func testFunctionWithAttribute() throws { + let function = Function("bar") { + Variable(.let, name: "message", type: "String", equals: "bar") + }.attribute("available") + + let generated = function.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("func bar")) + } + + @Test("Variable with attribute generates correct syntax") + func testVariableWithAttribute() throws { + let variable = Variable(.var, name: "bar", type: "String", equals: "bar") + .attribute("Published") + + let generated = variable.syntax.description + #expect(generated.contains("@Published")) + #expect(generated.contains("var bar")) + } + + @Test("Multiple attributes on class generates correct syntax") + func testMultipleAttributesOnClass() throws { + let classDecl = Class("Foo") { + Variable(.var, name: "bar", type: "String", equals: "bar") + } + .attribute("objc") + .attribute("MainActor") + + let generated = classDecl.syntax.description + #expect(generated.contains("@objc")) + #expect(generated.contains("@MainActor")) + #expect(generated.contains("class Foo")) + } + + @Test("Attribute with arguments generates correct syntax") + func testAttributeWithArguments() throws { + let attribute = Attribute("available", arguments: ["iOS", "17.0", "*"]) + + let generated = attribute.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("iOS")) + #expect(generated.contains("17.0")) + #expect(generated.contains("*")) + } + + @Test("Attribute with single argument generates correct syntax") + func testAttributeWithSingleArgument() throws { + let attribute = Attribute("available", argument: "iOS 17.0") + + let generated = attribute.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("iOS 17.0")) + } + + @Test("Comprehensive attribute example generates correct syntax") + func testComprehensiveAttributeExample() throws { + let classDecl = Class("Foo") { + Variable(.var, name: "bar", type: "String", equals: "bar") + .attribute("Published") + + Function("bar") { + Variable(.let, name: "message", type: "String", equals: "bar") + } + .attribute("available") + .attribute("MainActor") + + Function("baz") { + Variable(.let, name: "message", type: "String", equals: "baz") + } + .attribute("MainActor") + }.attribute("objc") + + let generated = classDecl.syntax.description + #expect(generated.contains("@objc")) + #expect(generated.contains("@Published")) + #expect(generated.contains("@available")) + #expect(generated.contains("@MainActor")) + #expect(generated.contains("class Foo")) + #expect(generated.contains("var bar")) + #expect(generated.contains("func bar")) + #expect(generated.contains("func baz")) + } + + @Test("Function with attribute arguments generates correct syntax") + func testFunctionWithAttributeArguments() throws { + let function = Function("bar") { + Variable(.let, name: "message", type: "String", equals: "bar") + }.attribute("available", arguments: ["iOS", "17.0", "*"]) + + let generated = function.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("iOS")) + #expect(generated.contains("17.0")) + #expect(generated.contains("*")) + #expect(generated.contains("func bar")) + } + + @Test("Class with attribute arguments generates correct syntax") + func testClassWithAttributeArguments() throws { + let classDecl = Class("Foo") { + Variable(.var, name: "bar", type: "String", equals: "bar") + }.attribute("available", arguments: ["iOS", "17.0"]) + + let generated = classDecl.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("iOS")) + #expect(generated.contains("17.0")) + #expect(generated.contains("class Foo")) + } + + @Test("Variable with attribute arguments generates correct syntax") + func testVariableWithAttributeArguments() throws { + let variable = Variable(.var, name: "bar", type: "String", equals: "bar") + .attribute("available", arguments: ["iOS", "17.0"]) + + let generated = variable.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("iOS")) + #expect(generated.contains("17.0")) + #expect(generated.contains("var bar")) + } + + @Test("Parameter with attribute generates correct syntax") + func testParameterWithAttribute() throws { + let function = Function("process") { + Parameter(name: "data", type: "Data") + .attribute("escaping") + } _: { + Variable(.let, name: "result", type: "String", equals: "processed") + } + + let generated = function.syntax.description + #expect(generated.contains("@escaping")) + #expect(generated.contains("data: Data")) + #expect(generated.contains("func process")) + } + + @Test("Parameter with attribute arguments generates correct syntax") + func testParameterWithAttributeArguments() throws { + let function = Function("validate") { + Parameter(name: "input", type: "String") + .attribute("available", arguments: ["iOS", "17.0"]) + } _: { + Variable(.let, name: "result", type: "Bool", equals: "true") + } + + let generated = function.syntax.description + #expect(generated.contains("@available")) + #expect(generated.contains("iOS")) + #expect(generated.contains("17.0")) + #expect(generated.contains("input: String")) + #expect(generated.contains("func validate")) + } +} diff --git a/Tests/SyntaxKitTests/ClassTests.swift b/Tests/SyntaxKitTests/ClassTests.swift index f9c3836..5b967d0 100644 --- a/Tests/SyntaxKitTests/ClassTests.swift +++ b/Tests/SyntaxKitTests/ClassTests.swift @@ -35,9 +35,9 @@ struct ClassTests { } @Test func testClassWithGenerics() { - let genericClass = Class("Container", generics: ["T"]) { + let genericClass = Class("Container") { Variable(.var, name: "value", type: "T") - } + }.generic("T") let expected = """ class Container { @@ -51,10 +51,10 @@ struct ClassTests { } @Test func testClassWithMultipleGenerics() { - let multiGenericClass = Class("Pair", generics: ["T", "U"]) { + let multiGenericClass = Class("Pair") { Variable(.var, name: "first", type: "T") Variable(.var, name: "second", type: "U") - } + }.generic("T", "U") let expected = """ class Pair { @@ -87,10 +87,10 @@ struct ClassTests { @Test func testClassWithMultipleInheritance() { let classWithMultipleInheritance = Class("AdvancedVehicle") { Variable(.var, name: "speed", type: "Int") - }.inherits("Vehicle", "Codable", "Equatable") + }.inherits("Vehicle") let expected = """ - class AdvancedVehicle: Vehicle, Codable, Equatable { + class AdvancedVehicle: Vehicle { var speed: Int } """ @@ -101,9 +101,9 @@ struct ClassTests { } @Test func testClassWithGenericsAndInheritance() { - let genericClassWithInheritance = Class("GenericContainer", generics: ["T"]) { + let genericClassWithInheritance = Class("GenericContainer") { Variable(.var, name: "items", type: "[T]") - }.inherits("Collection") + }.generic("T").inherits("Collection") let expected = """ class GenericContainer: Collection { @@ -117,9 +117,9 @@ struct ClassTests { } @Test func testFinalClassWithInheritanceAndGenerics() { - let finalGenericClass = Class("FinalGenericClass", generics: ["T"]) { + let finalGenericClass = Class("FinalGenericClass") { Variable(.var, name: "value", type: "T") - }.inherits("BaseClass").final() + }.generic("T").inherits("BaseClass").final() let expected = """ final class FinalGenericClass: BaseClass { diff --git a/Tests/SyntaxKitTests/StructTests.swift b/Tests/SyntaxKitTests/StructTests.swift index e578664..9aaf4df 100644 --- a/Tests/SyntaxKitTests/StructTests.swift +++ b/Tests/SyntaxKitTests/StructTests.swift @@ -4,7 +4,7 @@ import Testing struct StructTests { @Test func testGenericStruct() { - let stackStruct = Struct("Stack", generic: "Element") { + let stackStruct = Struct("Stack") { Variable(.var, name: "items", type: "[Element]", equals: "[]") Function("push") { @@ -30,7 +30,7 @@ struct StructTests { ComputedProperty("count", type: "Int") { Return { VariableExp("items").property("count") } } - } + }.generic("Element") let expectedCode = """ struct Stack { @@ -64,9 +64,9 @@ struct StructTests { } @Test func testGenericStructWithInheritance() { - let containerStruct = Struct("Container", generic: "T") { + let containerStruct = Struct("Container") { Variable(.var, name: "value", type: "T") - }.inherits("Equatable") + }.generic("T").inherits("Equatable") let expectedCode = """ struct Container: Equatable { From 85ab6c8cdc8ca6e9b13ef22012bf9b1a97128863 Mon Sep 17 00:00:00 2001 From: leogdion Date: Wed, 18 Jun 2025 21:23:30 -0400 Subject: [PATCH 04/10] Making a Code Review (#73) --- Sources/SyntaxKit/Attribute.swift | 6 +- Sources/SyntaxKit/CodeBlock+Generate.swift | 15 + Sources/SyntaxKit/CommentedCodeBlock.swift | 6 +- Sources/SyntaxKit/Enum.swift | 82 +++-- Sources/SyntaxKit/Group.swift | 2 +- Sources/SyntaxKit/Let.swift | 4 +- Sources/SyntaxKit/Parameter.swift | 8 +- Sources/SyntaxKit/ParameterExp.swift | 4 +- Sources/SyntaxKit/Parenthesized.swift | 55 ++++ Sources/SyntaxKit/VariableExp.swift | 12 +- Sources/SyntaxKit/parser/TokenVisitor.swift | 12 +- Sources/SyntaxKit/parser/TreeNode.swift | 50 +-- Sources/skit/main.swift | 3 +- .../AssertionMigrationTests.swift | 10 +- Tests/SyntaxKitTests/AttributeTests.swift | 26 +- Tests/SyntaxKitTests/BasicTests.swift | 4 +- Tests/SyntaxKitTests/BlackjackTests.swift | 6 +- Tests/SyntaxKitTests/ClassTests.swift | 20 +- .../CodeStyleMigrationTests.swift | 6 +- Tests/SyntaxKitTests/CommentTests.swift | 4 +- Tests/SyntaxKitTests/EdgeCaseTests.swift | 288 ++++++++++++++++++ Tests/SyntaxKitTests/ExtensionTests.swift | 22 +- .../FrameworkCompatibilityTests.swift | 18 +- Tests/SyntaxKitTests/FunctionTests.swift | 8 +- Tests/SyntaxKitTests/LiteralTests.swift | 4 +- Tests/SyntaxKitTests/LiteralValueTests.swift | 20 +- .../SyntaxKitTests/MainApplicationTests.swift | 195 ++++++++++++ Tests/SyntaxKitTests/MigrationTests.swift | 22 +- .../OptionsMacroIntegrationTests.swift | 18 +- Tests/SyntaxKitTests/ProtocolTests.swift | 22 +- Tests/SyntaxKitTests/String+Normalize.swift | 2 +- Tests/SyntaxKitTests/StructTests.swift | 8 +- Tests/SyntaxKitTests/TypeAliasTests.swift | 30 +- .../SyntaxKitTests/VariableStaticTests.swift | 24 +- 34 files changed, 799 insertions(+), 217 deletions(-) create mode 100644 Sources/SyntaxKit/Parenthesized.swift create mode 100644 Tests/SyntaxKitTests/EdgeCaseTests.swift create mode 100644 Tests/SyntaxKitTests/MainApplicationTests.swift diff --git a/Sources/SyntaxKit/Attribute.swift b/Sources/SyntaxKit/Attribute.swift index c3d909b..526a55a 100644 --- a/Sources/SyntaxKit/Attribute.swift +++ b/Sources/SyntaxKit/Attribute.swift @@ -31,10 +31,10 @@ import SwiftSyntax /// Internal representation of a Swift attribute with its arguments. internal struct AttributeInfo { - let name: String - let arguments: [String] + internal let name: String + internal let arguments: [String] - init(name: String, arguments: [String] = []) { + internal init(name: String, arguments: [String] = []) { self.name = name self.arguments = arguments } diff --git a/Sources/SyntaxKit/CodeBlock+Generate.swift b/Sources/SyntaxKit/CodeBlock+Generate.swift index c912232..9acbb9e 100644 --- a/Sources/SyntaxKit/CodeBlock+Generate.swift +++ b/Sources/SyntaxKit/CodeBlock+Generate.swift @@ -45,6 +45,21 @@ extension CodeBlock { item = .stmt(stmt) } else if let expr = self.syntax.as(ExprSyntax.self) { item = .expr(expr) + } else if let token = self.syntax.as(TokenSyntax.self) { + // Wrap TokenSyntax in DeclReferenceExprSyntax and then in ExprSyntax + let expr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) + item = .expr(expr) + } else if let switchCase = self.syntax.as(SwitchCaseSyntax.self) { + // Wrap SwitchCaseSyntax in a SwitchExprSyntax and treat it as an expression + // This is a fallback for when SwitchCase is used standalone + let switchExpr = SwitchExprSyntax( + switchKeyword: .keyword(.switch, trailingTrivia: .space), + subject: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_"))), + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + cases: SwitchCaseListSyntax([SwitchCaseListSyntax.Element(switchCase)]), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + item = .expr(ExprSyntax(switchExpr)) } else { fatalError( "Unsupported syntax type at top level: \(type(of: self.syntax)) generating from \(self)") diff --git a/Sources/SyntaxKit/CommentedCodeBlock.swift b/Sources/SyntaxKit/CommentedCodeBlock.swift index 351a5df..79f6ef3 100644 --- a/Sources/SyntaxKit/CommentedCodeBlock.swift +++ b/Sources/SyntaxKit/CommentedCodeBlock.swift @@ -33,10 +33,10 @@ import SwiftSyntax // MARK: - Wrapper `CodeBlock` that injects leading trivia internal struct CommentedCodeBlock: CodeBlock { - let base: CodeBlock - let lines: [Line] + internal let base: CodeBlock + internal let lines: [Line] - var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { // Shortcut if there are no comment lines guard !lines.isEmpty else { return base.syntax } diff --git a/Sources/SyntaxKit/Enum.swift b/Sources/SyntaxKit/Enum.swift index 82e6dd4..65a9183 100644 --- a/Sources/SyntaxKit/Enum.swift +++ b/Sources/SyntaxKit/Enum.swift @@ -145,33 +145,43 @@ public struct Enum: CodeBlock { /// A Swift `case` declaration inside an `enum`. public struct EnumCase: CodeBlock { private let name: String - private var value: String? - private var intValue: Int? + private var literalValue: Literal? /// Creates a `case` declaration. /// - Parameter name: The name of the case. public init(_ name: String) { self.name = name + self.literalValue = nil } - /// Sets the raw value of the case to a string. - /// - Parameter value: The string value. + /// Sets the raw value of the case to a Literal. + /// - Parameter value: The literal value. /// - Returns: A copy of the case with the raw value set. - public func equals(_ value: String) -> Self { + public func equals(_ value: Literal) -> Self { var copy = self - copy.value = value - copy.intValue = nil + copy.literalValue = value return copy } - /// Sets the raw value of the case to an integer. + /// Sets the raw value of the case to a string (for backward compatibility). + /// - Parameter value: The string value. + /// - Returns: A copy of the case with the raw value set. + public func equals(_ value: String) -> Self { + self.equals(.string(value)) + } + + /// Sets the raw value of the case to an integer (for backward compatibility). /// - Parameter value: The integer value. /// - Returns: A copy of the case with the raw value set. public func equals(_ value: Int) -> Self { - var copy = self - copy.value = nil - copy.intValue = value - return copy + self.equals(.integer(value)) + } + + /// Sets the raw value of the case to a float (for backward compatibility). + /// - Parameter value: The float value. + /// - Returns: A copy of the case with the raw value set. + public func equals(_ value: Double) -> Self { + self.equals(.float(value)) } public var syntax: SyntaxProtocol { @@ -179,22 +189,40 @@ public struct EnumCase: CodeBlock { let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) var initializer: InitializerClauseSyntax? - if let value = value { - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) - ]), - closingQuote: .stringQuoteToken() + if let literal = literalValue { + switch literal { + case .string(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: StringLiteralExprSyntax( + openingQuote: .stringQuoteToken(), + segments: StringLiteralSegmentListSyntax([ + .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) + ]), + closingQuote: .stringQuoteToken() + ) ) - ) - } else if let intValue = intValue { - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(intValue))) - ) + case .float(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: FloatLiteralExprSyntax(literal: .floatLiteral(String(value))) + ) + case .integer(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(value))) + ) + case .nil: + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) + ) + case .boolean(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) + ) + } } return EnumCaseDeclSyntax( diff --git a/Sources/SyntaxKit/Group.swift b/Sources/SyntaxKit/Group.swift index 7b3e824..329574a 100644 --- a/Sources/SyntaxKit/Group.swift +++ b/Sources/SyntaxKit/Group.swift @@ -31,7 +31,7 @@ import SwiftSyntax /// A group of code blocks. public struct Group: CodeBlock { - let members: [CodeBlock] + internal let members: [CodeBlock] /// Creates a group of code blocks. /// - Parameter content: A ``CodeBlockBuilder`` that provides the members of the group. diff --git a/Sources/SyntaxKit/Let.swift b/Sources/SyntaxKit/Let.swift index cd2d46d..354a2d7 100644 --- a/Sources/SyntaxKit/Let.swift +++ b/Sources/SyntaxKit/Let.swift @@ -31,8 +31,8 @@ import SwiftSyntax /// A Swift `let` declaration for use in an `if` statement. public struct Let: CodeBlock { - let name: String - let value: String + internal let name: String + internal let value: String /// Creates a `let` declaration for an `if` statement. /// - Parameters: diff --git a/Sources/SyntaxKit/Parameter.swift b/Sources/SyntaxKit/Parameter.swift index 75703c2..3090d6c 100644 --- a/Sources/SyntaxKit/Parameter.swift +++ b/Sources/SyntaxKit/Parameter.swift @@ -33,10 +33,10 @@ import SwiftSyntax /// A parameter for a function or initializer. public struct Parameter: CodeBlock { - let name: String - let type: String - let defaultValue: String? - let isUnnamed: Bool + internal let name: String + internal let type: String + internal let defaultValue: String? + internal let isUnnamed: Bool internal var attributes: [AttributeInfo] = [] /// Creates a parameter for a function or initializer. diff --git a/Sources/SyntaxKit/ParameterExp.swift b/Sources/SyntaxKit/ParameterExp.swift index 02274e8..87294a8 100644 --- a/Sources/SyntaxKit/ParameterExp.swift +++ b/Sources/SyntaxKit/ParameterExp.swift @@ -31,8 +31,8 @@ import SwiftSyntax /// A parameter for a function call. public struct ParameterExp: CodeBlock { - let name: String - let value: String + internal let name: String + internal let value: String /// Creates a parameter for a function call. /// - Parameters: diff --git a/Sources/SyntaxKit/Parenthesized.swift b/Sources/SyntaxKit/Parenthesized.swift new file mode 100644 index 0000000..be8959b --- /dev/null +++ b/Sources/SyntaxKit/Parenthesized.swift @@ -0,0 +1,55 @@ +// +// Parenthesized.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A code block that wraps its content in parentheses. +public struct Parenthesized: CodeBlock { + private let content: CodeBlock + + /// Creates a parenthesized code block. + /// - Parameter content: The code block to wrap in parentheses. + public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + let blocks = content() + precondition(blocks.count == 1, "Parenthesized expects exactly one code block.") + self.content = blocks[0] + } + + public var syntax: SyntaxProtocol { + ExprSyntax( + TupleExprSyntax( + leftParen: .leftParenToken(), + elements: LabeledExprListSyntax([ + LabeledExprSyntax(expression: content.expr) + ]), + rightParen: .rightParenToken() + ) + ) + } +} diff --git a/Sources/SyntaxKit/VariableExp.swift b/Sources/SyntaxKit/VariableExp.swift index 5616290..fb55e86 100644 --- a/Sources/SyntaxKit/VariableExp.swift +++ b/Sources/SyntaxKit/VariableExp.swift @@ -31,7 +31,7 @@ import SwiftSyntax /// An expression that refers to a variable. public struct VariableExp: CodeBlock { - let name: String + internal let name: String /// Creates a variable expression. /// - Parameter name: The name of the variable. @@ -71,8 +71,8 @@ public struct VariableExp: CodeBlock { /// An expression that accesses a property on a base expression. public struct PropertyAccessExp: CodeBlock { - let baseName: String - let propertyName: String + internal let baseName: String + internal let propertyName: String /// Creates a property access expression. /// - Parameters: @@ -97,9 +97,9 @@ public struct PropertyAccessExp: CodeBlock { /// An expression that calls a function. public struct FunctionCallExp: CodeBlock { - let baseName: String - let methodName: String - let parameters: [ParameterExp] + internal let baseName: String + internal let methodName: String + internal let parameters: [ParameterExp] /// Creates a function call expression. /// - Parameters: diff --git a/Sources/SyntaxKit/parser/TokenVisitor.swift b/Sources/SyntaxKit/parser/TokenVisitor.swift index aad7ca5..f377831 100644 --- a/Sources/SyntaxKit/parser/TokenVisitor.swift +++ b/Sources/SyntaxKit/parser/TokenVisitor.swift @@ -30,9 +30,9 @@ import Foundation @_spi(RawSyntax) import SwiftSyntax -final class TokenVisitor: SyntaxRewriter { +internal final class TokenVisitor: SyntaxRewriter { // var list = [String]() - var tree = [TreeNode]() + internal var tree = [TreeNode]() private var current: TreeNode! private var index = 0 @@ -40,14 +40,14 @@ final class TokenVisitor: SyntaxRewriter { private let locationConverter: SourceLocationConverter private let showMissingTokens: Bool - init(locationConverter: SourceLocationConverter, showMissingTokens: Bool) { + internal init(locationConverter: SourceLocationConverter, showMissingTokens: Bool) { self.locationConverter = locationConverter self.showMissingTokens = showMissingTokens super.init(viewMode: showMissingTokens ? .all : .sourceAccurate) } // swiftlint:disable:next cyclomatic_complexity function_body_length - override func visitPre(_ node: Syntax) { + override internal func visitPre(_ node: Syntax) { let syntaxNodeType = node.syntaxNodeType let className: String @@ -177,7 +177,7 @@ final class TokenVisitor: SyntaxRewriter { current = treeNode } - override func visit(_ token: TokenSyntax) -> TokenSyntax { + override internal func visit(_ token: TokenSyntax) -> TokenSyntax { current.text = token .text .escapeHTML() @@ -199,7 +199,7 @@ final class TokenVisitor: SyntaxRewriter { return token } - override func visitPost(_ node: Syntax) { + override internal func visitPost(_ node: Syntax) { if let parent = current.parent { current = tree[parent] } else { diff --git a/Sources/SyntaxKit/parser/TreeNode.swift b/Sources/SyntaxKit/parser/TreeNode.swift index 4c35089..a83ec0d 100644 --- a/Sources/SyntaxKit/parser/TreeNode.swift +++ b/Sources/SyntaxKit/parser/TreeNode.swift @@ -29,16 +29,16 @@ import Foundation -final class TreeNode: Codable { - let id: Int - var parent: Int? +internal final class TreeNode: Codable { + internal let id: Int + internal var parent: Int? - var text: String - var range = Range( + internal var text: String + internal var range = Range( startRow: 0, startColumn: 0, endRow: 0, endColumn: 0) - var structure = [StructureProperty]() - var type: SyntaxType - var token: Token? + internal var structure = [StructureProperty]() + internal var type: SyntaxType + internal var token: Token? init(id: Int, text: String, range: Range, type: SyntaxType) { self.id = id @@ -71,11 +71,11 @@ extension TreeNode: CustomStringConvertible { } } -struct Range: Codable, Equatable { - let startRow: Int - let startColumn: Int - let endRow: Int - let endColumn: Int +internal struct Range: Codable, Equatable { + internal let startRow: Int + internal let startColumn: Int + internal let endRow: Int + internal let endColumn: Int } extension Range: CustomStringConvertible { @@ -91,10 +91,10 @@ extension Range: CustomStringConvertible { } } -struct StructureProperty: Codable, Equatable { - let name: String - let value: StructureValue? - let ref: String? +internal struct StructureProperty: Codable, Equatable { + internal let name: String + internal let value: StructureValue? + internal let ref: String? init(name: String, value: StructureValue? = nil, ref: String? = nil) { self.name = name.escapeHTML() @@ -115,9 +115,9 @@ extension StructureProperty: CustomStringConvertible { } } -struct StructureValue: Codable, Equatable { - let text: String - let kind: String? +internal struct StructureValue: Codable, Equatable { + internal let text: String + internal let kind: String? init(text: String, kind: String? = nil) { self.text = text.escapeHTML().replaceHTMLWhitespacesToSymbols() @@ -136,7 +136,7 @@ extension StructureValue: CustomStringConvertible { } } -enum SyntaxType: String, Codable { +internal enum SyntaxType: String, Codable { case decl case expr case pattern @@ -145,10 +145,10 @@ enum SyntaxType: String, Codable { case other } -struct Token: Codable, Equatable { - let kind: String - var leadingTrivia: String - var trailingTrivia: String +internal struct Token: Codable, Equatable { + internal let kind: String + internal var leadingTrivia: String + internal var trailingTrivia: String init(kind: String, leadingTrivia: String, trailingTrivia: String) { self.kind = kind.escapeHTML() diff --git a/Sources/skit/main.swift b/Sources/skit/main.swift index d7952fe..b500a63 100644 --- a/Sources/skit/main.swift +++ b/Sources/skit/main.swift @@ -31,7 +31,8 @@ import Foundation import SyntaxKit // Read Swift code from stdin -let code = String(data: FileHandle.standardInput.readDataToEndOfFile(), encoding: .utf8) ?? "" +internal let code = + String(data: FileHandle.standardInput.readDataToEndOfFile(), encoding: .utf8) ?? "" do { // Parse the code using SyntaxKit diff --git a/Tests/SyntaxKitTests/AssertionMigrationTests.swift b/Tests/SyntaxKitTests/AssertionMigrationTests.swift index a6d03f2..3c8d824 100644 --- a/Tests/SyntaxKitTests/AssertionMigrationTests.swift +++ b/Tests/SyntaxKitTests/AssertionMigrationTests.swift @@ -4,10 +4,10 @@ import Testing /// Tests specifically focused on assertion migration from XCTest to Swift Testing /// Ensures all assertion patterns from the original tests work correctly with #expect() -struct AssertionMigrationTests { +internal struct AssertionMigrationTests { // MARK: - XCTAssertEqual Migration Tests - @Test func testEqualityAssertionMigration() throws { + @Test internal func testEqualityAssertionMigration() throws { // Test the most common migration: XCTAssertEqual -> #expect(a == b) let function = Function("test", returns: "String") { Return { @@ -29,7 +29,7 @@ struct AssertionMigrationTests { // MARK: - XCTAssertFalse Migration Tests - @Test func testFalseAssertionMigration() { + @Test internal func testFalseAssertionMigration() { let syntax = Group { Variable(.let, name: "test", type: "String", equals: "\"value\"") } @@ -42,7 +42,7 @@ struct AssertionMigrationTests { // MARK: - Complex Assertion Migration Tests - @Test func testNormalizedStringComparisonMigration() throws { + @Test internal func testNormalizedStringComparisonMigration() throws { let blackjackCard = Struct("Card") { Enum("Suit") { EnumCase("hearts").equals("♡") @@ -68,7 +68,7 @@ struct AssertionMigrationTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testMultipleAssertionsInSingleTest() { + @Test internal func testMultipleAssertionsInSingleTest() { let generated = "struct Test { var value: Int }" // Test multiple assertions in one test method diff --git a/Tests/SyntaxKitTests/AttributeTests.swift b/Tests/SyntaxKitTests/AttributeTests.swift index 717811a..3c70141 100644 --- a/Tests/SyntaxKitTests/AttributeTests.swift +++ b/Tests/SyntaxKitTests/AttributeTests.swift @@ -30,9 +30,9 @@ import SyntaxKit import Testing -@Suite struct AttributeTests { +@Suite internal struct AttributeTests { @Test("Class with attribute generates correct syntax") - func testClassWithAttribute() throws { + internal func testClassWithAttribute() throws { let classDecl = Class("Foo") { Variable(.var, name: "bar", type: "String", equals: "bar") }.attribute("objc") @@ -43,7 +43,7 @@ import Testing } @Test("Function with attribute generates correct syntax") - func testFunctionWithAttribute() throws { + internal func testFunctionWithAttribute() throws { let function = Function("bar") { Variable(.let, name: "message", type: "String", equals: "bar") }.attribute("available") @@ -54,7 +54,7 @@ import Testing } @Test("Variable with attribute generates correct syntax") - func testVariableWithAttribute() throws { + internal func testVariableWithAttribute() throws { let variable = Variable(.var, name: "bar", type: "String", equals: "bar") .attribute("Published") @@ -64,7 +64,7 @@ import Testing } @Test("Multiple attributes on class generates correct syntax") - func testMultipleAttributesOnClass() throws { + internal func testMultipleAttributesOnClass() throws { let classDecl = Class("Foo") { Variable(.var, name: "bar", type: "String", equals: "bar") } @@ -78,7 +78,7 @@ import Testing } @Test("Attribute with arguments generates correct syntax") - func testAttributeWithArguments() throws { + internal func testAttributeWithArguments() throws { let attribute = Attribute("available", arguments: ["iOS", "17.0", "*"]) let generated = attribute.syntax.description @@ -89,7 +89,7 @@ import Testing } @Test("Attribute with single argument generates correct syntax") - func testAttributeWithSingleArgument() throws { + internal func testAttributeWithSingleArgument() throws { let attribute = Attribute("available", argument: "iOS 17.0") let generated = attribute.syntax.description @@ -98,7 +98,7 @@ import Testing } @Test("Comprehensive attribute example generates correct syntax") - func testComprehensiveAttributeExample() throws { + internal func testComprehensiveAttributeExample() throws { let classDecl = Class("Foo") { Variable(.var, name: "bar", type: "String", equals: "bar") .attribute("Published") @@ -127,7 +127,7 @@ import Testing } @Test("Function with attribute arguments generates correct syntax") - func testFunctionWithAttributeArguments() throws { + internal func testFunctionWithAttributeArguments() throws { let function = Function("bar") { Variable(.let, name: "message", type: "String", equals: "bar") }.attribute("available", arguments: ["iOS", "17.0", "*"]) @@ -141,7 +141,7 @@ import Testing } @Test("Class with attribute arguments generates correct syntax") - func testClassWithAttributeArguments() throws { + internal func testClassWithAttributeArguments() throws { let classDecl = Class("Foo") { Variable(.var, name: "bar", type: "String", equals: "bar") }.attribute("available", arguments: ["iOS", "17.0"]) @@ -154,7 +154,7 @@ import Testing } @Test("Variable with attribute arguments generates correct syntax") - func testVariableWithAttributeArguments() throws { + internal func testVariableWithAttributeArguments() throws { let variable = Variable(.var, name: "bar", type: "String", equals: "bar") .attribute("available", arguments: ["iOS", "17.0"]) @@ -166,7 +166,7 @@ import Testing } @Test("Parameter with attribute generates correct syntax") - func testParameterWithAttribute() throws { + internal func testParameterWithAttribute() throws { let function = Function("process") { Parameter(name: "data", type: "Data") .attribute("escaping") @@ -181,7 +181,7 @@ import Testing } @Test("Parameter with attribute arguments generates correct syntax") - func testParameterWithAttributeArguments() throws { + internal func testParameterWithAttributeArguments() throws { let function = Function("validate") { Parameter(name: "input", type: "String") .attribute("available", arguments: ["iOS", "17.0"]) diff --git a/Tests/SyntaxKitTests/BasicTests.swift b/Tests/SyntaxKitTests/BasicTests.swift index bfc9433..2fb77b3 100644 --- a/Tests/SyntaxKitTests/BasicTests.swift +++ b/Tests/SyntaxKitTests/BasicTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct BasicTests { - @Test func testBlackjackCardExample() throws { +internal struct BasicTests { + @Test internal func testBlackjackCardExample() throws { let blackjackCard = Struct("BlackjackCard") { Enum("Suit") { EnumCase("spades").equals("♠") diff --git a/Tests/SyntaxKitTests/BlackjackTests.swift b/Tests/SyntaxKitTests/BlackjackTests.swift index 16ab0d0..0d71ceb 100644 --- a/Tests/SyntaxKitTests/BlackjackTests.swift +++ b/Tests/SyntaxKitTests/BlackjackTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct BlackjackTests { - @Test func testBlackjackCardExample() throws { +internal struct BlackjackTests { + @Test internal func testBlackjackCardExample() throws { let syntax = Struct("BlackjackCard") { Enum("Suit") { EnumCase("spades").equals("♠") @@ -71,7 +71,7 @@ struct BlackjackTests { } // swiftlint:disable:next function_body_length - @Test func testFullBlackjackCardExample() throws { + @Test internal func testFullBlackjackCardExample() throws { // swiftlint:disable:next closure_body_length let syntax = Struct("BlackjackCard") { Enum("Suit") { diff --git a/Tests/SyntaxKitTests/ClassTests.swift b/Tests/SyntaxKitTests/ClassTests.swift index 5b967d0..8c5bc1b 100644 --- a/Tests/SyntaxKitTests/ClassTests.swift +++ b/Tests/SyntaxKitTests/ClassTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct ClassTests { - @Test func testClassWithInheritance() { +internal struct ClassTests { + @Test internal func testClassWithInheritance() { let carClass = Class("Car") { Variable(.var, name: "brand", type: "String") Variable(.var, name: "numberOfWheels", type: "Int") @@ -21,7 +21,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testEmptyClass() { + @Test internal func testEmptyClass() { let emptyClass = Class("EmptyClass") {} let expected = """ @@ -34,7 +34,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testClassWithGenerics() { + @Test internal func testClassWithGenerics() { let genericClass = Class("Container") { Variable(.var, name: "value", type: "T") }.generic("T") @@ -50,7 +50,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testClassWithMultipleGenerics() { + @Test internal func testClassWithMultipleGenerics() { let multiGenericClass = Class("Pair") { Variable(.var, name: "first", type: "T") Variable(.var, name: "second", type: "U") @@ -68,7 +68,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testFinalClass() { + @Test internal func testFinalClass() { let finalClass = Class("FinalClass") { Variable(.var, name: "value", type: "String") }.final() @@ -84,7 +84,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testClassWithMultipleInheritance() { + @Test internal func testClassWithMultipleInheritance() { let classWithMultipleInheritance = Class("AdvancedVehicle") { Variable(.var, name: "speed", type: "Int") }.inherits("Vehicle") @@ -100,7 +100,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testClassWithGenericsAndInheritance() { + @Test internal func testClassWithGenericsAndInheritance() { let genericClassWithInheritance = Class("GenericContainer") { Variable(.var, name: "items", type: "[T]") }.generic("T").inherits("Collection") @@ -116,7 +116,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testFinalClassWithInheritanceAndGenerics() { + @Test internal func testFinalClassWithInheritanceAndGenerics() { let finalGenericClass = Class("FinalGenericClass") { Variable(.var, name: "value", type: "T") }.generic("T").inherits("BaseClass").final() @@ -132,7 +132,7 @@ struct ClassTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testClassWithFunctions() { + @Test internal func testClassWithFunctions() { let classWithFunctions = Class("Calculator") { Function("add", returns: "Int") { Parameter(name: "a", type: "Int") diff --git a/Tests/SyntaxKitTests/CodeStyleMigrationTests.swift b/Tests/SyntaxKitTests/CodeStyleMigrationTests.swift index 08aea89..8a9daa8 100644 --- a/Tests/SyntaxKitTests/CodeStyleMigrationTests.swift +++ b/Tests/SyntaxKitTests/CodeStyleMigrationTests.swift @@ -4,10 +4,10 @@ import Testing /// Tests for code style and API simplification changes introduced during Swift Testing migration /// Validates the simplified Swift APIs and formatting changes -struct CodeStyleMigrationTests { +internal struct CodeStyleMigrationTests { // MARK: - CharacterSet Simplification Tests - @Test func testCharacterSetSimplification() { + @Test internal func testCharacterSetSimplification() { // Test that .whitespacesAndNewlines works instead of CharacterSet.whitespacesAndNewlines let testString = "\n test content \n\t" @@ -20,7 +20,7 @@ struct CodeStyleMigrationTests { // MARK: - Indentation and Formatting Tests - @Test func testConsistentIndentationInMigratedCode() throws { + @Test internal func testConsistentIndentationInMigratedCode() throws { // Test that the indentation changes in the migrated code work correctly let syntax = Struct("IndentationTest") { Variable(.let, name: "property1", type: "String") diff --git a/Tests/SyntaxKitTests/CommentTests.swift b/Tests/SyntaxKitTests/CommentTests.swift index 331852e..e56fdcd 100644 --- a/Tests/SyntaxKitTests/CommentTests.swift +++ b/Tests/SyntaxKitTests/CommentTests.swift @@ -2,9 +2,9 @@ import Testing @testable import SyntaxKit -struct CommentTests { +internal struct CommentTests { // swiftlint:disable:next function_body_length - @Test func testCommentInjection() { + @Test internal func testCommentInjection() { // swiftlint:disable:next closure_body_length let syntax = Group { Struct("Card") { diff --git a/Tests/SyntaxKitTests/EdgeCaseTests.swift b/Tests/SyntaxKitTests/EdgeCaseTests.swift new file mode 100644 index 0000000..a2b63b6 --- /dev/null +++ b/Tests/SyntaxKitTests/EdgeCaseTests.swift @@ -0,0 +1,288 @@ +import Testing + +@testable import SyntaxKit + +internal struct EdgeCaseTests { + // MARK: - Error Handling Tests + + @Test("Infix with wrong number of operands throws fatal error") + internal func testInfixWrongOperandCount() { + // This test documents the expected behavior + // In a real scenario, this would cause a fatal error + // We can't easily test fatalError in unit tests, but we can document it + let infix = Infix("+") { + // Only one operand - should cause fatal error + VariableExp("x") + } + + // The fatal error would occur when accessing .syntax + // This test documents the expected behavior + #expect(true) // Placeholder - fatal errors can't be easily tested + } + + @Test("Return with no expressions throws fatal error") + internal func testReturnWithNoExpressions() { + // This test documents the expected behavior + // In a real scenario, this would cause a fatal error + let returnStmt = Return { + // Empty - should cause fatal error + } + + // The fatal error would occur when accessing .syntax + // This test documents the expected behavior + #expect(true) // Placeholder - fatal errors can't be easily tested + } + + // MARK: - Switch and Case Tests + + @Test("Switch with multiple patterns generates correct syntax") + internal func testSwitchWithMultiplePatterns() throws { + let switchStmt = Switch("value") { + SwitchCase("1") { + Return { VariableExp("one") } + } + SwitchCase("2") { + Return { VariableExp("two") } + } + } + + let generated = switchStmt.generateCode() + #expect(generated.contains("switch value")) + #expect(generated.contains("case 1:")) + #expect(generated.contains("case 2:")) + } + + @Test("SwitchCase with multiple patterns generates correct syntax") + internal func testSwitchCaseWithMultiplePatterns() throws { + let switchCase = SwitchCase("1", "2", "3") { + Return { VariableExp("number") } + } + + let generated = switchCase.generateCode() + #expect(generated.contains("case 1, 2, 3:")) + } + + // MARK: - Complex Expression Tests + + @Test("Infix with complex expressions generates correct syntax") + internal func testInfixWithComplexExpressions() throws { + let infix = Infix("*") { + Parenthesized { + Infix("+") { + VariableExp("a") + VariableExp("b") + } + } + Parenthesized { + Infix("-") { + VariableExp("c") + VariableExp("d") + } + } + } + + let generated = infix.generateCode() + #expect(generated.contains("(a + b) * (c - d)")) + } + + @Test("Return with VariableExp generates correct syntax") + internal func testReturnWithVariableExp() throws { + let returnStmt = Return { + VariableExp("result") + } + + let generated = returnStmt.generateCode() + #expect(generated.contains("return result")) + } + + @Test("Return with complex expression generates correct syntax") + internal func testReturnWithComplexExpression() throws { + let returnStmt = Return { + Infix("+") { + VariableExp("a") + VariableExp("b") + } + } + + let generated = returnStmt.generateCode() + #expect(generated.contains("return a + b")) + } + + // MARK: - CodeBlock Expression Tests + + @Test("CodeBlock expr with TokenSyntax wraps in DeclReferenceExpr") + internal func testCodeBlockExprWithTokenSyntax() throws { + let variableExp = VariableExp("x") + let expr = variableExp.expr + + let generated = expr.description + #expect(generated.contains("x")) + } + + // MARK: - Code Generation Edge Cases + + @Test("CodeBlock generateCode with CodeBlockItemListSyntax") + internal func testCodeBlockGenerateCodeWithItemList() throws { + let group = Group { + Variable(.let, name: "x", type: "Int", equals: "1") + Variable(.let, name: "y", type: "Int", equals: "2") + } + + let generated = group.generateCode() + #expect(generated.contains("let x : Int = 1")) + #expect(generated.contains("let y : Int = 2")) + } + + @Test("CodeBlock generateCode with single declaration") + internal func testCodeBlockGenerateCodeWithSingleDeclaration() throws { + let variable = Variable(.let, name: "x", type: "Int", equals: "1") + + let generated = variable.generateCode() + #expect(generated.contains("let x : Int = 1")) + } + + @Test("CodeBlock generateCode with single statement") + internal func testCodeBlockGenerateCodeWithSingleStatement() throws { + let assignment = Assignment("x", "42") + + let generated = assignment.generateCode() + #expect(generated.contains("x = 42")) + } + + @Test("CodeBlock generateCode with single expression") + internal func testCodeBlockGenerateCodeWithSingleExpression() throws { + let variableExp = VariableExp("x") + + let generated = variableExp.generateCode() + #expect(generated.contains("x")) + } + + // MARK: - Complex Type Tests + + @Test("TypeAlias with complex nested types") + internal func testTypeAliasWithComplexNestedTypes() throws { + let typeAlias = TypeAlias("ComplexType", equals: "Array>>") + + let generated = typeAlias.generateCode() + #expect( + generated.normalize().contains( + "typealias ComplexType = Array>>".normalize())) + } + + @Test("TypeAlias with multiple generic parameters") + internal func testTypeAliasWithMultipleGenericParameters() throws { + let typeAlias = TypeAlias("Result", equals: "Result") + + let generated = typeAlias.generateCode().normalize() + #expect(generated.contains("typealias Result = Result".normalize())) + } + + // MARK: - Function Parameter Tests + + @Test("Function with unnamed parameter generates correct syntax") + internal func testFunctionWithUnnamedParameter() throws { + let function = Function("process") { + Parameter(name: "data", type: "Data", isUnnamed: true) + } _: { + Variable(.let, name: "result", type: "String", equals: "processed") + } + + let generated = function.generateCode() + #expect(generated.contains("func process(_ data: Data)")) + } + + @Test("Function with parameter default value generates correct syntax") + internal func testFunctionWithParameterDefaultValue() throws { + let function = Function("greet") { + Parameter(name: "name", type: "String", defaultValue: "\"World\"") + } _: { + Variable(.let, name: "message", type: "String", equals: "greeting") + } + + let generated = function.generateCode() + #expect(generated.contains("func greet(name: String = \"World\")")) + } + + // MARK: - Enum Case Tests + + @Test("EnumCase with string raw value generates correct syntax") + internal func testEnumCaseWithStringRawValue() throws { + let enumDecl = Enum("Status") { + EnumCase("active").equals(Literal.string("active")) + EnumCase("inactive").equals(Literal.string("inactive")) + } + + let generated = enumDecl.generateCode().normalize() + #expect(generated.contains("case active = \"active\"")) + #expect(generated.contains("case inactive = \"inactive\"")) + } + + @Test("EnumCase with double raw value generates correct syntax") + internal func testEnumCaseWithDoubleRawValue() throws { + let enumDecl = Enum("Precision") { + EnumCase("low").equals(Literal.float(0.1)) + EnumCase("high").equals(Literal.float(0.001)) + } + + let generated = enumDecl.generateCode().normalize() + #expect(generated.contains("case low = 0.1")) + #expect(generated.contains("case high = 0.001")) + } + + // MARK: - Computed Property Tests + + @Test("ComputedProperty with complex return expression") + internal func testComputedPropertyWithComplexReturn() throws { + let computedProperty = ComputedProperty("description", type: "String") { + Return { + VariableExp("name").call("appending") { + ParameterExp(name: "", value: "\" - \" + String(count)") + } + } + } + + let generated = computedProperty.generateCode().normalize() + #expect(generated.contains("var description: String")) + #expect(generated.contains("return name.appending(\" - \" + String(count))")) + } + + // MARK: - Comment Integration Tests + + @Test("ComputedProperty with comments generates correct syntax") + internal func testComputedPropertyWithComments() throws { + let computedProperty = ComputedProperty("formattedName", type: "String") { + Return { + VariableExp("name").property("uppercased") + } + }.comment { + Line(.doc, "Returns the name in uppercase format") + } + + let generated = computedProperty.generateCode() + #expect(generated.contains("/// Returns the name in uppercase format")) + #expect(generated.contains("var formattedName : String")) + } + + // MARK: - Literal Tests + + @Test("Literal with nil generates correct syntax") + internal func testLiteralWithNil() throws { + let literal = Literal.nil + let generated = literal.generateCode() + #expect(generated.contains("nil")) + } + + @Test("Literal with boolean generates correct syntax") + internal func testLiteralWithBoolean() throws { + let literal = Literal.boolean(true) + let generated = literal.generateCode() + #expect(generated.contains("true")) + } + + @Test("Literal with float generates correct syntax") + internal func testLiteralWithFloat() throws { + let literal = Literal.float(3.14159) + let generated = literal.generateCode() + #expect(generated.contains("3.14159")) + } +} diff --git a/Tests/SyntaxKitTests/ExtensionTests.swift b/Tests/SyntaxKitTests/ExtensionTests.swift index b04190d..ee57490 100644 --- a/Tests/SyntaxKitTests/ExtensionTests.swift +++ b/Tests/SyntaxKitTests/ExtensionTests.swift @@ -31,10 +31,10 @@ import Testing @testable import SyntaxKit -struct ExtensionTests { +internal struct ExtensionTests { // MARK: - Basic Extension Tests - @Test func testBasicExtension() { + @Test internal func testBasicExtension() { let extensionDecl = Extension("String") { Variable(.let, name: "test", type: "Int", equals: "42") } @@ -45,7 +45,7 @@ struct ExtensionTests { #expect(generated.contains("let test: Int = 42")) } - @Test func testExtensionWithMultipleMembers() { + @Test internal func testExtensionWithMultipleMembers() { let extensionDecl = Extension("Array") { Variable(.let, name: "isEmpty", type: "Bool", equals: "true") Variable(.let, name: "count", type: "Int", equals: "0") @@ -60,7 +60,7 @@ struct ExtensionTests { // MARK: - Extension with Inheritance Tests - @Test func testExtensionWithSingleInheritance() { + @Test internal func testExtensionWithSingleInheritance() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") }.inherits("MappedValueRepresentable") @@ -71,7 +71,7 @@ struct ExtensionTests { #expect(generated.contains("typealias MappedType = String")) } - @Test func testExtensionWithMultipleInheritance() { + @Test internal func testExtensionWithMultipleInheritance() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") }.inherits("MappedValueRepresentable", "MappedValueRepresented") @@ -83,7 +83,7 @@ struct ExtensionTests { #expect(generated.contains("typealias MappedType = String")) } - @Test func testExtensionWithoutInheritance() { + @Test internal func testExtensionWithoutInheritance() { let extensionDecl = Extension("MyType") { Variable(.let, name: "constant", type: "String", equals: "value") } @@ -97,7 +97,7 @@ struct ExtensionTests { // MARK: - Extension with Complex Members Tests - @Test func testExtensionWithStaticVariables() { + @Test internal func testExtensionWithStaticVariables() { let array: [String] = ["a", "b", "c"] let dict: [Int: String] = [1: "one", 2: "two"] @@ -118,7 +118,7 @@ struct ExtensionTests { #expect(generated.contains("2: \"two\"")) } - @Test func testExtensionWithFunctions() { + @Test internal func testExtensionWithFunctions() { let extensionDecl = Extension("String") { Function("uppercasedFirst", returns: "String") { Return { @@ -136,7 +136,7 @@ struct ExtensionTests { // MARK: - Edge Cases - @Test func testExtensionWithEmptyBody() { + @Test internal func testExtensionWithEmptyBody() { let extensionDecl = Extension("EmptyType") { // Empty body } @@ -148,7 +148,7 @@ struct ExtensionTests { #expect(generated.contains("}")) } - @Test func testExtensionWithSpecialCharactersInName() { + @Test internal func testExtensionWithSpecialCharactersInName() { let extensionDecl = Extension("MyType") { Variable(.let, name: "generic", type: "T", equals: "nil") } @@ -159,7 +159,7 @@ struct ExtensionTests { #expect(generated.contains("let generic: T = nil")) } - @Test func testInheritsMethodReturnsNewInstance() { + @Test internal func testInheritsMethodReturnsNewInstance() { let original = Extension("Test") { Variable(.let, name: "value", type: "Int", equals: "42") } diff --git a/Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift b/Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift index d16bdc0..33f0de8 100644 --- a/Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift +++ b/Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift @@ -4,17 +4,17 @@ import Testing /// Tests to ensure compatibility and feature parity between XCTest and Swift Testing /// Validates that the migration maintains all testing capabilities -struct FrameworkCompatibilityTests { +internal struct FrameworkCompatibilityTests { // MARK: - Test Organization Migration Tests - @Test func testStructBasedOrganization() { + @Test internal func testStructBasedOrganization() { // Test that struct-based test organization works // This replaces: final class TestClass: XCTestCase let testExecuted = true #expect(testExecuted) } - @Test func testMethodAnnotationMigration() throws { + @Test internal func testMethodAnnotationMigration() throws { // Test that @Test annotation works with throws // This replaces: func testMethod() throws let syntax = Enum("TestEnum") { @@ -29,7 +29,7 @@ struct FrameworkCompatibilityTests { // MARK: - Error Handling Compatibility Tests - @Test func testThrowingTestCompatibility() throws { + @Test internal func testThrowingTestCompatibility() throws { // Ensure throws declaration works properly with @Test let function = Function("throwingFunction", returns: "String") { Parameter(name: "input", type: "String") @@ -45,7 +45,7 @@ struct FrameworkCompatibilityTests { // MARK: - Complex DSL Compatibility Tests - @Test func testFullBlackjackCompatibility() throws { + @Test internal func testFullBlackjackCompatibility() throws { // Test complex DSL patterns work with new framework let syntax = Struct("BlackjackCard") { Enum("Suit") { @@ -80,7 +80,7 @@ struct FrameworkCompatibilityTests { // MARK: - Function Generation Compatibility Tests - @Test func testFunctionGenerationCompatibility() throws { + @Test internal func testFunctionGenerationCompatibility() throws { let function = Function("calculateValue", returns: "Int") { Parameter(name: "multiplier", type: "Int") Parameter(name: "base", type: "Int", defaultValue: "10") @@ -101,7 +101,7 @@ struct FrameworkCompatibilityTests { // MARK: - Comment Injection Compatibility Tests - @Test func testCommentInjectionCompatibility() { + @Test internal func testCommentInjectionCompatibility() { let syntax = Struct("DocumentedStruct") { Variable(.let, name: "value", type: "String") .comment { @@ -121,7 +121,7 @@ struct FrameworkCompatibilityTests { // MARK: - Migration Regression Tests - @Test func testNoRegressionInCodeGeneration() { + @Test internal func testNoRegressionInCodeGeneration() { // Ensure migration doesn't introduce regressions let simpleStruct = Struct("Point") { Variable(.var, name: "x", type: "Double", equals: "0.0") @@ -135,7 +135,7 @@ struct FrameworkCompatibilityTests { #expect(generated.contains("var y: Double = 0.0".normalize())) } - @Test func testLiteralGeneration() { + @Test internal func testLiteralGeneration() { let group = Group { Return { Literal.integer(100) diff --git a/Tests/SyntaxKitTests/FunctionTests.swift b/Tests/SyntaxKitTests/FunctionTests.swift index 797002e..50f0da9 100644 --- a/Tests/SyntaxKitTests/FunctionTests.swift +++ b/Tests/SyntaxKitTests/FunctionTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct FunctionTests { - @Test func testBasicFunction() throws { +internal struct FunctionTests { + @Test internal func testBasicFunction() throws { let function = Function("calculateSum", returns: "Int") { Parameter(name: "a", type: "Int") Parameter(name: "b", type: "Int") @@ -27,7 +27,7 @@ struct FunctionTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testStaticFunction() throws { + @Test internal func testStaticFunction() throws { let function = Function( "createInstance", returns: "MyType", { @@ -55,7 +55,7 @@ struct FunctionTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testMutatingFunction() throws { + @Test internal func testMutatingFunction() throws { let function = Function( "updateValue", { diff --git a/Tests/SyntaxKitTests/LiteralTests.swift b/Tests/SyntaxKitTests/LiteralTests.swift index 255675a..28fb10f 100644 --- a/Tests/SyntaxKitTests/LiteralTests.swift +++ b/Tests/SyntaxKitTests/LiteralTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct LiteralTests { - @Test func testGroupWithLiterals() { +internal struct LiteralTests { + @Test internal func testGroupWithLiterals() { let group = Group { Return { Literal.integer(1) diff --git a/Tests/SyntaxKitTests/LiteralValueTests.swift b/Tests/SyntaxKitTests/LiteralValueTests.swift index 1517dcb..ce7cd09 100644 --- a/Tests/SyntaxKitTests/LiteralValueTests.swift +++ b/Tests/SyntaxKitTests/LiteralValueTests.swift @@ -31,37 +31,37 @@ import Testing @testable import SyntaxKit -struct LiteralValueTests { +internal struct LiteralValueTests { // MARK: - Array LiteralValue Tests - @Test func testArrayStringTypeName() { + @Test internal func testArrayStringTypeName() { let array: [String] = ["a", "b", "c"] #expect(array.typeName == "[String]") } - @Test func testArrayStringLiteralString() { + @Test internal func testArrayStringLiteralString() { let array: [String] = ["a", "b", "c"] #expect(array.literalString == "[\"a\", \"b\", \"c\"]") } - @Test func testEmptyArrayStringLiteralString() { + @Test internal func testEmptyArrayStringLiteralString() { let array: [String] = [] #expect(array.literalString == "[]") } - @Test func testArrayStringWithSpecialCharacters() { + @Test internal func testArrayStringWithSpecialCharacters() { let array: [String] = ["hello world", "test\"quote", "line\nbreak"] #expect(array.literalString == "[\"hello world\", \"test\\\"quote\", \"line\\nbreak\"]") } // MARK: - Dictionary LiteralValue Tests - @Test func testDictionaryIntStringTypeName() { + @Test internal func testDictionaryIntStringTypeName() { let dict: [Int: String] = [1: "a", 2: "b"] #expect(dict.typeName == "[Int: String]") } - @Test func testDictionaryIntStringLiteralString() { + @Test internal func testDictionaryIntStringLiteralString() { let dict: [Int: String] = [1: "a", 2: "b", 3: "c"] let literal = dict.literalString @@ -73,12 +73,12 @@ struct LiteralValueTests { #expect(literal.hasSuffix("]")) } - @Test func testEmptyDictionaryLiteralString() { + @Test internal func testEmptyDictionaryLiteralString() { let dict: [Int: String] = [:] #expect(dict.literalString == "[]") } - @Test func testDictionaryWithSpecialCharacters() { + @Test internal func testDictionaryWithSpecialCharacters() { let dict: [Int: String] = [1: "hello world", 2: "test\"quote"] let literal = dict.literalString @@ -91,7 +91,7 @@ struct LiteralValueTests { // MARK: - Dictionary Ordering Tests - @Test func testDictionaryOrderingIsConsistent() { + @Test internal func testDictionaryOrderingIsConsistent() { let dict1: [Int: String] = [2: "b", 1: "a", 3: "c"] let dict2: [Int: String] = [1: "a", 2: "b", 3: "c"] diff --git a/Tests/SyntaxKitTests/MainApplicationTests.swift b/Tests/SyntaxKitTests/MainApplicationTests.swift new file mode 100644 index 0000000..397838e --- /dev/null +++ b/Tests/SyntaxKitTests/MainApplicationTests.swift @@ -0,0 +1,195 @@ +import Foundation +import Testing + +@testable import SyntaxKit + +internal struct MainApplicationTests { + // MARK: - Main Application Error Handling Tests + + @Test("Main application handles valid input") + internal func testMainApplicationValidInput() throws { + // This test simulates the main application behavior + // We can't easily test the main function directly, but we can test its components + + let code = "let x = 42" + let response = try SyntaxParser.parse(code: code, options: ["fold"]) + + // Test JSON serialization (part of main application logic) + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("syntax")) + #expect(jsonString!.contains("let")) + } + + @Test("Main application handles empty input") + internal func testMainApplicationEmptyInput() throws { + let code = "" + let response = try SyntaxParser.parse(code: code, options: []) + + // Test JSON serialization with empty result + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("syntax")) + } + + @Test("Main application handles parsing errors") + internal func testMainApplicationHandlesParsingErrors() throws { + let invalidCode = "struct {" + + // The parser doesn't throw errors for invalid syntax, it returns a result + let response = try SyntaxParser.parse(code: invalidCode, options: []) + + // Test error JSON serialization (part of main application logic) + let jsonData = try JSONSerialization.data(withJSONObject: ["error": "Invalid syntax"]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("error")) + #expect(jsonString!.contains("Invalid syntax")) + } + + @Test("Main application handles JSON serialization errors") + internal func testMainApplicationHandlesJSONSerializationErrors() throws { + // Test with a response that might cause JSON serialization issues + let code = "let x = 42" + let response = try SyntaxParser.parse(code: code, options: []) + + // This should work fine, but we're testing the JSON serialization path + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + } + + // MARK: - File I/O Simulation Tests + + @Test("Main application handles large input") + internal func testMainApplicationHandlesLargeInput() throws { + // Generate a large Swift file to test performance + var largeCode = "" + for index in 1...50 { + largeCode += """ + struct Struct\(index) { + let property\(index): String + func method\(index)() -> String { + return "value\(index)" + } + } + + """ + } + + let response = try SyntaxParser.parse(code: largeCode, options: ["fold"]) + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("Struct1")) + #expect(jsonString!.contains("Struct50")) + } + + @Test("Main application handles unicode input") + internal func testMainApplicationHandlesUnicodeInput() throws { + let unicodeCode = """ + let emoji = "🚀" + let unicode = "café" + let chinese = "你好" + """ + + let response = try SyntaxParser.parse(code: unicodeCode, options: []) + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("emoji")) + #expect(jsonString!.contains("unicode")) + #expect(jsonString!.contains("chinese")) + } + + // MARK: - Error Response Format Tests + + @Test("Main application error response format") + internal func testMainApplicationErrorResponseFormat() throws { + // Test the error response format that the main application would generate + let testError = NSError( + domain: "TestDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "Test error message"]) + + let errorResponse = ["error": testError.localizedDescription] + let jsonData = try JSONSerialization.data(withJSONObject: errorResponse) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("error")) + #expect(jsonString!.contains("Test error message")) + } + + @Test("Main application handles encoding errors") + internal func testMainApplicationHandlesEncodingErrors() throws { + let code = "let x = 42" + let response = try SyntaxParser.parse(code: code, options: []) + + // Test UTF-8 encoding (part of main application logic) + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("syntax")) + } + + // MARK: - Integration Tests + + @Test("Main application integration with complex Swift code") + internal func testMainApplicationIntegrationWithComplexSwiftCode() throws { + let code = """ + @objc class MyClass: NSObject { + @Published var property: String = "default" + + func method(@escaping completion: @escaping (String) -> Void) { + completion("result") + } + + enum NestedEnum: Int { + case first = 1 + case second = 2 + } + } + """ + + let response = try SyntaxParser.parse(code: code, options: ["fold"]) + + // Test JSON serialization (part of main application logic) + let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) + let jsonString = String(data: jsonData, encoding: .utf8) + + #expect(jsonString != nil) + #expect(jsonString!.contains("syntax")) + #expect(jsonString!.contains("class")) + #expect(jsonString!.contains("MyClass")) + } + + @Test("Main application handles different parser options") + internal func testMainApplicationHandlesDifferentParserOptions() throws { + let code = "let x = 42" + + let response1 = try SyntaxParser.parse(code: code, options: []) + let response2 = try SyntaxParser.parse(code: code, options: ["fold"]) + + // Test JSON serialization for both responses + let jsonData1 = try JSONSerialization.data(withJSONObject: ["syntax": response1.syntaxJSON]) + let jsonString1 = String(data: jsonData1, encoding: .utf8) + + let jsonData2 = try JSONSerialization.data(withJSONObject: ["syntax": response2.syntaxJSON]) + let jsonString2 = String(data: jsonData2, encoding: .utf8) + + #expect(jsonString1 != nil) + #expect(jsonString2 != nil) + #expect(jsonString1!.contains("syntax")) + #expect(jsonString2!.contains("syntax")) + #expect(jsonString1!.contains("let")) + #expect(jsonString2!.contains("let")) + } +} diff --git a/Tests/SyntaxKitTests/MigrationTests.swift b/Tests/SyntaxKitTests/MigrationTests.swift index ddcc5a7..b97b32d 100644 --- a/Tests/SyntaxKitTests/MigrationTests.swift +++ b/Tests/SyntaxKitTests/MigrationTests.swift @@ -4,16 +4,16 @@ import Testing /// Tests specifically for verifying the Swift Testing framework migration /// These tests ensure that the migration from XCTest to Swift Testing works correctly -struct MigrationTests { +internal struct MigrationTests { // MARK: - Basic Test Structure Migration Tests - @Test func testStructBasedTestExecution() { + @Test internal func testStructBasedTestExecution() { // Test that struct-based tests execute properly let result = true #expect(result == true) } - @Test func testThrowingTestMethod() throws { + @Test internal func testThrowingTestMethod() throws { // Test that @Test works with throws declaration let syntax = Struct("TestStruct") { Variable(.let, name: "value", type: "String") @@ -25,21 +25,21 @@ struct MigrationTests { // MARK: - Assertion Migration Tests - @Test func testExpectEqualityAssertion() { + @Test internal func testExpectEqualityAssertion() { // Test #expect() replacement for XCTAssertEqual let actual = "test" let expected = "test" #expect(actual == expected) } - @Test func testExpectBooleanAssertion() { + @Test internal func testExpectBooleanAssertion() { // Test #expect() replacement for XCTAssertTrue/XCTAssertFalse let condition = true #expect(condition) #expect(!false) } - @Test func testExpectEmptyStringAssertion() { + @Test internal func testExpectEmptyStringAssertion() { // Test #expect() replacement for XCTAssertFalse(string.isEmpty) let generated = "non-empty string" #expect(!generated.isEmpty) @@ -47,7 +47,7 @@ struct MigrationTests { // MARK: - Code Generation Testing with New Framework - @Test func testBasicCodeGenerationWithNewFramework() throws { + @Test internal func testBasicCodeGenerationWithNewFramework() throws { let blackjackCard = Struct("BlackjackCard") { Enum("Suit") { EnumCase("spades").equals("♠") @@ -78,7 +78,7 @@ struct MigrationTests { // MARK: - String Options Migration Tests - @Test func testStringCompareOptionsSimplification() { + @Test internal func testStringCompareOptionsSimplification() { // Test that .regularExpression works instead of String.CompareOptions.regularExpression let testString = "public func test() { }" let result = testString.replacingOccurrences( @@ -87,7 +87,7 @@ struct MigrationTests { #expect(result == expected) } - @Test func testCharacterSetSimplification() { + @Test internal func testCharacterSetSimplification() { // Test that .whitespacesAndNewlines works instead of CharacterSet.whitespacesAndNewlines let testString = " test \n" let result = testString.trimmingCharacters(in: .whitespacesAndNewlines) @@ -97,7 +97,7 @@ struct MigrationTests { // MARK: - Complex Code Generation Tests - @Test func testComplexStructGeneration() throws { + @Test internal func testComplexStructGeneration() throws { let syntax = Struct("TestCard") { Variable(.let, name: "rank", type: "String") Variable(.let, name: "suit", type: "String") @@ -118,7 +118,7 @@ struct MigrationTests { #expect(generated.contains("func description() -> String".normalize())) } - @Test func testMigrationBackwardCompatibility() { + @Test internal func testMigrationBackwardCompatibility() { // Ensure that the migrated tests maintain the same functionality let group = Group { Return { diff --git a/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift b/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift index b013daa..af6106d 100644 --- a/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift +++ b/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift @@ -31,10 +31,10 @@ import Testing @testable import SyntaxKit -struct OptionsMacroIntegrationTests { +internal struct OptionsMacroIntegrationTests { // MARK: - Enum with Raw Values (Dictionary) Tests - @Test func testEnumWithRawValuesCreatesDictionary() { + @Test internal func testEnumWithRawValuesCreatesDictionary() { // Simulate the Options macro expansion for an enum with raw values let keyValues: [Int: String] = [2: "a", 5: "b", 6: "c", 12: "d"] @@ -56,7 +56,7 @@ struct OptionsMacroIntegrationTests { #expect(generated.contains("12: \"d\"")) } - @Test func testEnumWithoutRawValuesCreatesArray() { + @Test internal func testEnumWithoutRawValuesCreatesArray() { // Simulate the Options macro expansion for an enum without raw values let caseNames: [String] = ["red", "green", "blue"] @@ -75,7 +75,7 @@ struct OptionsMacroIntegrationTests { // MARK: - Complex Integration Tests - @Test func testCompleteOptionsMacroWorkflow() { + @Test internal func testCompleteOptionsMacroWorkflow() { // This test demonstrates the complete workflow that the Options macro would use // Step 1: Determine if enum has raw values (simulated) @@ -110,7 +110,7 @@ struct OptionsMacroIntegrationTests { #expect(generated.contains("3: \"third\"")) } - @Test func testOptionsMacroWorkflowWithoutRawValues() { + @Test internal func testOptionsMacroWorkflowWithoutRawValues() { // Test the workflow for enums without raw values let hasRawValues = false @@ -140,7 +140,7 @@ struct OptionsMacroIntegrationTests { // MARK: - Edge Cases - @Test func testEmptyEnumCases() { + @Test internal func testEmptyEnumCases() { let caseNames: [String] = [] let extensionDecl = Extension("EmptyEnum") { @@ -156,7 +156,7 @@ struct OptionsMacroIntegrationTests { #expect(generated.contains("static let mappedValues: [String] = []")) } - @Test func testEmptyDictionary() { + @Test internal func testEmptyDictionary() { let keyValues: [Int: String] = [:] let extensionDecl = Extension("EmptyDictEnum") { @@ -173,7 +173,7 @@ struct OptionsMacroIntegrationTests { #expect(generated.contains("static let mappedValues: [Int: String] = []")) } - @Test func testSpecialCharactersInCaseNames() { + @Test internal func testSpecialCharactersInCaseNames() { let caseNames: [String] = ["case_with_underscore", "case-with-dash", "caseWithCamelCase"] let extensionDecl = Extension("SpecialEnum") { @@ -194,7 +194,7 @@ struct OptionsMacroIntegrationTests { // MARK: - API Validation Tests - @Test func testNewSyntaxKitAPICompleteness() { + @Test internal func testNewSyntaxKitAPICompleteness() { // Verify that all the new API components work together correctly // Test LiteralValue protocol diff --git a/Tests/SyntaxKitTests/ProtocolTests.swift b/Tests/SyntaxKitTests/ProtocolTests.swift index 31a3c55..dec6071 100644 --- a/Tests/SyntaxKitTests/ProtocolTests.swift +++ b/Tests/SyntaxKitTests/ProtocolTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct ProtocolTests { - @Test func testSimpleProtocol() { +internal struct ProtocolTests { + @Test internal func testSimpleProtocol() { let vehicleProtocol = Protocol("Vehicle") { PropertyRequirement("numberOfWheels", type: "Int", access: .get) PropertyRequirement("brand", type: "String", access: .getSet) @@ -27,7 +27,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testEmptyProtocol() { + @Test internal func testEmptyProtocol() { let emptyProtocol = Protocol("EmptyProtocol") {} let expected = """ @@ -40,7 +40,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testProtocolWithInheritance() { + @Test internal func testProtocolWithInheritance() { let protocolWithInheritance = Protocol("MyProtocol") { PropertyRequirement("value", type: "String", access: .getSet) }.inherits("Equatable", "Hashable") @@ -56,7 +56,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testFunctionRequirementWithParameters() { + @Test internal func testFunctionRequirementWithParameters() { let protocolWithFunction = Protocol("Calculator") { FunctionRequirement("add", returns: "Int") { Parameter(name: "a", type: "Int") @@ -75,7 +75,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testStaticFunctionRequirement() { + @Test internal func testStaticFunctionRequirement() { let protocolWithStaticFunction = Protocol("Factory") { FunctionRequirement("create", returns: "Self").static() } @@ -91,7 +91,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testMutatingFunctionRequirement() { + @Test internal func testMutatingFunctionRequirement() { let protocolWithMutatingFunction = Protocol("Resettable") { FunctionRequirement("reset").mutating() } @@ -107,7 +107,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testPropertyRequirementGetOnly() { + @Test internal func testPropertyRequirementGetOnly() { let propertyReq = PropertyRequirement("readOnlyProperty", type: "String", access: .get) let prtcl = Protocol("TestProtocol") { propertyReq @@ -124,7 +124,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testPropertyRequirementGetSet() { + @Test internal func testPropertyRequirementGetSet() { let propertyReq = PropertyRequirement("readWriteProperty", type: "Int", access: .getSet) let prtcl = Protocol("TestProtocol") { propertyReq @@ -141,7 +141,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testFunctionRequirementWithDefaultParameters() { + @Test internal func testFunctionRequirementWithDefaultParameters() { let functionReq = FunctionRequirement("process", returns: "String") { Parameter(name: "input", type: "String") Parameter(name: "options", type: "ProcessingOptions", defaultValue: "ProcessingOptions()") @@ -161,7 +161,7 @@ struct ProtocolTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testComplexProtocolWithMixedRequirements() { + @Test internal func testComplexProtocolWithMixedRequirements() { let complexProtocol = Protocol("ComplexProtocol") { PropertyRequirement("id", type: "UUID", access: .get) PropertyRequirement("name", type: "String", access: .getSet) diff --git a/Tests/SyntaxKitTests/String+Normalize.swift b/Tests/SyntaxKitTests/String+Normalize.swift index 5343b37..bc1c614 100644 --- a/Tests/SyntaxKitTests/String+Normalize.swift +++ b/Tests/SyntaxKitTests/String+Normalize.swift @@ -1,7 +1,7 @@ import Foundation extension String { - func normalize() -> String { + internal func normalize() -> String { self .replacingOccurrences(of: "//.*$", with: "", options: .regularExpression) .replacingOccurrences(of: "\\s*:\\s*", with: ": ", options: .regularExpression) diff --git a/Tests/SyntaxKitTests/StructTests.swift b/Tests/SyntaxKitTests/StructTests.swift index 9aaf4df..61ba952 100644 --- a/Tests/SyntaxKitTests/StructTests.swift +++ b/Tests/SyntaxKitTests/StructTests.swift @@ -2,8 +2,8 @@ import Testing @testable import SyntaxKit -struct StructTests { - @Test func testGenericStruct() { +internal struct StructTests { + @Test internal func testGenericStruct() { let stackStruct = Struct("Stack") { Variable(.var, name: "items", type: "[Element]", equals: "[]") @@ -63,7 +63,7 @@ struct StructTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testGenericStructWithInheritance() { + @Test internal func testGenericStructWithInheritance() { let containerStruct = Struct("Container") { Variable(.var, name: "value", type: "T") }.generic("T").inherits("Equatable") @@ -79,7 +79,7 @@ struct StructTests { #expect(normalizedGenerated == normalizedExpected) } - @Test func testNonGenericStruct() { + @Test internal func testNonGenericStruct() { let simpleStruct = Struct("Point") { Variable(.var, name: "x", type: "Double") Variable(.var, name: "y", type: "Double") diff --git a/Tests/SyntaxKitTests/TypeAliasTests.swift b/Tests/SyntaxKitTests/TypeAliasTests.swift index c67c4eb..62f47cf 100644 --- a/Tests/SyntaxKitTests/TypeAliasTests.swift +++ b/Tests/SyntaxKitTests/TypeAliasTests.swift @@ -31,31 +31,31 @@ import Testing @testable import SyntaxKit -struct TypeAliasTests { +internal struct TypeAliasTests { // MARK: - Basic TypeAlias Tests - @Test func testBasicTypeAlias() { + @Test internal func testBasicTypeAlias() { let typeAlias = TypeAlias("MappedType", equals: "String") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias MappedType = String")) } - @Test func testTypeAliasWithComplexType() { + @Test internal func testTypeAliasWithComplexType() { let typeAlias = TypeAlias("ResultType", equals: "Result") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias ResultType = Result")) } - @Test func testTypeAliasWithGenericType() { + @Test internal func testTypeAliasWithGenericType() { let typeAlias = TypeAlias("ArrayType", equals: "Array") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias ArrayType = Array")) } - @Test func testTypeAliasWithOptionalType() { + @Test internal func testTypeAliasWithOptionalType() { let typeAlias = TypeAlias("OptionalString", equals: "String?") let generated = typeAlias.generateCode().normalize() @@ -64,7 +64,7 @@ struct TypeAliasTests { // MARK: - TypeAlias in Context Tests - @Test func testTypeAliasInExtension() { + @Test internal func testTypeAliasInExtension() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") Variable(.let, name: "test", type: "MappedType", equals: "value") @@ -77,7 +77,7 @@ struct TypeAliasTests { #expect(generated.contains("let test: MappedType = value")) } - @Test func testTypeAliasInStruct() { + @Test internal func testTypeAliasInStruct() { let structDecl = Struct("Container") { TypeAlias("ElementType", equals: "String") Variable(.let, name: "element", type: "ElementType") @@ -90,7 +90,7 @@ struct TypeAliasTests { #expect(generated.contains("let element: ElementType")) } - @Test func testTypeAliasInEnum() { + @Test internal func testTypeAliasInEnum() { let enumDecl = Enum("Result") { TypeAlias("SuccessType", equals: "String") TypeAlias("FailureType", equals: "Error") @@ -109,35 +109,35 @@ struct TypeAliasTests { // MARK: - Edge Cases - @Test func testTypeAliasWithSpecialCharacters() { + @Test internal func testTypeAliasWithSpecialCharacters() { let typeAlias = TypeAlias("GenericType", equals: "Array") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias GenericType = Array")) } - @Test func testTypeAliasWithProtocolComposition() { + @Test internal func testTypeAliasWithProtocolComposition() { let typeAlias = TypeAlias("ProtocolType", equals: "Protocol1 & Protocol2") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias ProtocolType = Protocol1 & Protocol2")) } - @Test func testTypeAliasWithFunctionType() { + @Test internal func testTypeAliasWithFunctionType() { let typeAlias = TypeAlias("Handler", equals: "(String) -> Void") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias Handler = (String) -> Void")) } - @Test func testTypeAliasWithTupleType() { + @Test internal func testTypeAliasWithTupleType() { let typeAlias = TypeAlias("Coordinate", equals: "(x: Double, y: Double)") let generated = typeAlias.generateCode().normalize() #expect(generated.contains("typealias Coordinate = (x: Double, y: Double)")) } - @Test func testTypeAliasWithClosureType() { + @Test internal func testTypeAliasWithClosureType() { let typeAlias = TypeAlias("Callback", equals: "@escaping (Result) -> Void") let generated = typeAlias.generateCode().normalize() @@ -146,7 +146,7 @@ struct TypeAliasTests { // MARK: - Integration Tests - @Test func testTypeAliasWithStaticVariable() { + @Test internal func testTypeAliasWithStaticVariable() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") Variable(.let, name: "mappedValues", equals: ["a", "b", "c"]).static() @@ -159,7 +159,7 @@ struct TypeAliasTests { #expect(generated.contains("static let mappedValues: [String] = [\"a\", \"b\", \"c\"]")) } - @Test func testTypeAliasWithDictionaryVariable() { + @Test internal func testTypeAliasWithDictionaryVariable() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") Variable(.let, name: "mappedValues", equals: [1: "a", 2: "b"]).static() diff --git a/Tests/SyntaxKitTests/VariableStaticTests.swift b/Tests/SyntaxKitTests/VariableStaticTests.swift index 38e1936..54612d1 100644 --- a/Tests/SyntaxKitTests/VariableStaticTests.swift +++ b/Tests/SyntaxKitTests/VariableStaticTests.swift @@ -31,17 +31,17 @@ import Testing @testable import SyntaxKit -struct VariableStaticTests { +internal struct VariableStaticTests { // MARK: - Static Variable Tests - @Test func testStaticVariableWithStringLiteral() { + @Test internal func testStaticVariableWithStringLiteral() { let variable = Variable(.let, name: "test", type: "String", equals: "hello").static() let generated = variable.generateCode().normalize() #expect(generated.contains("static let test: String = hello")) } - @Test func testStaticVariableWithArrayLiteral() { + @Test internal func testStaticVariableWithArrayLiteral() { let array: [String] = ["a", "b", "c"] let variable = Variable(.let, name: "mappedValues", equals: array).static() let generated = variable.generateCode().normalize() @@ -49,7 +49,7 @@ struct VariableStaticTests { #expect(generated.contains("static let mappedValues: [String] = [\"a\", \"b\", \"c\"]")) } - @Test func testStaticVariableWithDictionaryLiteral() { + @Test internal func testStaticVariableWithDictionaryLiteral() { let dict: [Int: String] = [1: "a", 2: "b", 3: "c"] let variable = Variable(.let, name: "mappedValues", equals: dict).static() let generated = variable.generateCode().normalize() @@ -60,7 +60,7 @@ struct VariableStaticTests { #expect(generated.contains("3: \"c\"")) } - @Test func testStaticVariableWithVar() { + @Test internal func testStaticVariableWithVar() { let variable = Variable(.var, name: "counter", type: "Int", equals: "0").static() let generated = variable.generateCode().normalize() @@ -69,7 +69,7 @@ struct VariableStaticTests { // MARK: - Non-Static Variable Tests - @Test func testNonStaticVariableWithLiteral() { + @Test internal func testNonStaticVariableWithLiteral() { let array: [String] = ["x", "y", "z"] let variable = Variable(.let, name: "values", equals: array) let generated = variable.generateCode().normalize() @@ -78,7 +78,7 @@ struct VariableStaticTests { #expect(!generated.contains("static")) } - @Test func testNonStaticVariableWithDictionary() { + @Test internal func testNonStaticVariableWithDictionary() { let dict: [Int: String] = [10: "ten", 20: "twenty"] let variable = Variable(.let, name: "lookup", equals: dict) let generated = variable.generateCode().normalize() @@ -91,7 +91,7 @@ struct VariableStaticTests { // MARK: - Static Method Tests - @Test func testStaticMethodReturnsNewInstance() { + @Test internal func testStaticMethodReturnsNewInstance() { let original = Variable(.let, name: "test", type: "String", equals: "value") let staticVersion = original.static() @@ -107,7 +107,7 @@ struct VariableStaticTests { #expect(staticGenerated.contains("static")) } - @Test func testStaticMethodPreservesOtherProperties() { + @Test internal func testStaticMethodPreservesOtherProperties() { let original = Variable(.var, name: "test", type: "String", equals: "value") let staticVersion = original.static() @@ -127,7 +127,7 @@ struct VariableStaticTests { // MARK: - Edge Cases - @Test func testEmptyArrayLiteral() { + @Test internal func testEmptyArrayLiteral() { let array: [String] = [] let variable = Variable(.let, name: "empty", equals: array).static() let generated = variable.generateCode().normalize() @@ -135,7 +135,7 @@ struct VariableStaticTests { #expect(generated.contains("static let empty: [String] = []")) } - @Test func testEmptyDictionaryLiteral() { + @Test internal func testEmptyDictionaryLiteral() { let dict: [Int: String] = [:] let variable = Variable(.let, name: "empty", equals: dict).static() let generated = variable.generateCode().normalize() @@ -143,7 +143,7 @@ struct VariableStaticTests { #expect(generated.contains("static let empty: [Int: String] = []")) } - @Test func testMultipleStaticCalls() { + @Test internal func testMultipleStaticCalls() { let variable = Variable(.let, name: "test", type: "String", equals: "value").static().static() let generated = variable.generateCode().normalize() From f158317dbeb034db11370eefb5e5681d331fd1ce Mon Sep 17 00:00:00 2001 From: leogdion Date: Sat, 21 Jun 2025 07:01:46 -0400 Subject: [PATCH 05/10] Adding Conditionals (#74) --- .swiftlint.yml | 1 + .../attributes/code.swift | 0 .../attributes/dsl.swift | 0 .../attributes/syntax.json | 0 Examples/Completed/conditionals/code.swift | 154 ++++++ Examples/Completed/conditionals/dsl.swift | 222 ++++++++ Examples/Completed/conditionals/syntax.json | 1 + Examples/Completed/for_loops/code.swift | 29 ++ Examples/Completed/for_loops/dsl.swift | 71 +++ Examples/Completed/for_loops/syntax.json | 1 + .../protocols/code.swift | 2 - Examples/Completed/protocols/dsl.swift | 106 ++++ Examples/Completed/protocols/syntax.json | 1 + Package.swift | 1 + Sources/SyntaxKit/Array+LiteralValue.swift | 51 ++ Sources/SyntaxKit/ArrayLiteral.swift | 74 +++ Sources/SyntaxKit/Assignment.swift | 69 +-- Sources/SyntaxKit/Break.swift | 58 +++ Sources/SyntaxKit/Call.swift | 84 +++ Sources/SyntaxKit/Case.swift | 46 +- Sources/SyntaxKit/Class.swift | 6 +- Sources/SyntaxKit/Continue.swift | 58 +++ Sources/SyntaxKit/Default.swift | 4 +- .../SyntaxKit/Dictionary+LiteralValue.swift | 51 ++ Sources/SyntaxKit/DictionaryLiteral.swift | 98 ++++ Sources/SyntaxKit/Enum.swift | 134 +---- Sources/SyntaxKit/EnumCase.swift | 144 ++++++ Sources/SyntaxKit/ExprCodeBlock.swift | 36 ++ Sources/SyntaxKit/Fallthrough.swift | 44 ++ Sources/SyntaxKit/For.swift | 140 +++++ Sources/SyntaxKit/Guard.swift | 139 +++++ Sources/SyntaxKit/If.swift | 190 +++++-- Sources/SyntaxKit/Init.swift | 21 +- Sources/SyntaxKit/Let.swift | 17 +- Sources/SyntaxKit/Literal+Convenience.swift | 54 ++ Sources/SyntaxKit/Literal+ExprCodeBlock.swift | 117 +++++ Sources/SyntaxKit/Literal.swift | 164 ++++-- Sources/SyntaxKit/LiteralValue.swift | 39 ++ Sources/SyntaxKit/Parameter.swift | 9 + Sources/SyntaxKit/ParameterExp.swift | 29 +- Sources/SyntaxKit/PatternConvertible.swift | 127 +++++ Sources/SyntaxKit/PlusAssign.swift | 50 +- Sources/SyntaxKit/Struct.swift | 29 +- Sources/SyntaxKit/Switch.swift | 19 +- Sources/SyntaxKit/SwitchCase.swift | 106 +++- Sources/SyntaxKit/SwitchLet.swift | 55 ++ Sources/SyntaxKit/Then.swift | 73 +++ Sources/SyntaxKit/Tuple.swift | 12 + Sources/SyntaxKit/TupleLiteral.swift | 91 ++++ Sources/SyntaxKit/TuplePattern.swift | 72 +++ Sources/SyntaxKit/TuplePatternCodeBlock.swift | 78 +++ Sources/SyntaxKit/Variable+Initializers.swift | 275 ++++++++++ Sources/SyntaxKit/Variable.swift | 74 +-- Sources/SyntaxKit/VariableDecl.swift | 14 +- Sources/SyntaxKit/VariableExp.swift | 8 +- Sources/SyntaxKit/While.swift | 99 ++++ Sources/SyntaxKit/parser/SourceRange.swift | 50 ++ .../SyntaxKit/parser/String+Extensions.swift | 38 ++ .../SyntaxKit/parser/StructureProperty.swift | 54 ++ Sources/SyntaxKit/parser/StructureValue.swift | 51 ++ Sources/SyntaxKit/parser/SyntaxParser.swift | 3 +- Sources/SyntaxKit/parser/SyntaxType.swift | 39 ++ Sources/SyntaxKit/parser/Token.swift | 54 ++ Sources/SyntaxKit/parser/TokenVisitor.swift | 6 +- Sources/SyntaxKit/parser/TreeNode.swift | 110 +--- .../SyntaxKitTests/Integration/.swiftlint.yml | 5 + .../BlackjackCardTests.swift} | 15 +- .../{ => Integration}/BlackjackTests.swift | 80 ++- .../{ => Integration}/CommentTests.swift | 2 - .../CompleteProtocolsExampleTests.swift | 297 +++++++++++ .../ConditionalsExampleTests.swift | 486 ++++++++++++++++++ .../Integration/ForLoopsExampleTests.swift | 151 ++++++ .../{ => Unit}/AssertionMigrationTests.swift | 8 +- .../{ => Unit}/AttributeTests.swift | 0 Tests/SyntaxKitTests/Unit/CallTests.swift | 120 +++++ .../{ => Unit}/ClassTests.swift | 42 +- .../{ => Unit}/CodeStyleMigrationTests.swift | 4 +- .../Unit/ConditionalsTests.swift | 50 ++ .../{ => Unit}/EdgeCaseTests.swift | 8 +- .../{ => Unit}/ExtensionTests.swift | 18 +- Tests/SyntaxKitTests/Unit/ForLoopTests.swift | 45 ++ .../FrameworkCompatibilityTests.swift | 4 +- .../{ => Unit}/FunctionTests.swift | 10 +- .../{ => Unit}/LiteralTests.swift | 0 .../{ => Unit}/LiteralValueTests.swift | 105 ++++ .../{ => Unit}/MainApplicationTests.swift | 24 +- .../{ => Unit}/MigrationTests.swift | 12 +- .../OptionsMacroIntegrationTests.swift | 26 +- .../Unit/PatternConvertibleTests.swift | 89 ++++ .../{ => Unit}/ProtocolTests.swift | 34 +- .../{ => Unit}/String+Normalize.swift | 1 - .../{ => Unit}/StructTests.swift | 46 +- .../{ => Unit}/TypeAliasTests.swift | 9 +- .../{ => Unit}/VariableStaticTests.swift | 36 +- codecov.yml | 1 + 95 files changed, 5118 insertions(+), 662 deletions(-) rename Examples/{Remaining => Completed}/attributes/code.swift (100%) rename Examples/{Remaining => Completed}/attributes/dsl.swift (100%) rename Examples/{Remaining => Completed}/attributes/syntax.json (100%) create mode 100644 Examples/Completed/conditionals/code.swift create mode 100644 Examples/Completed/conditionals/dsl.swift create mode 100644 Examples/Completed/conditionals/syntax.json create mode 100644 Examples/Completed/for_loops/code.swift create mode 100644 Examples/Completed/for_loops/dsl.swift create mode 100644 Examples/Completed/for_loops/syntax.json rename Examples/{Remaining => Completed}/protocols/code.swift (98%) create mode 100644 Examples/Completed/protocols/dsl.swift create mode 100644 Examples/Completed/protocols/syntax.json create mode 100644 Sources/SyntaxKit/Array+LiteralValue.swift create mode 100644 Sources/SyntaxKit/ArrayLiteral.swift create mode 100644 Sources/SyntaxKit/Break.swift create mode 100644 Sources/SyntaxKit/Call.swift create mode 100644 Sources/SyntaxKit/Continue.swift create mode 100644 Sources/SyntaxKit/Dictionary+LiteralValue.swift create mode 100644 Sources/SyntaxKit/DictionaryLiteral.swift create mode 100644 Sources/SyntaxKit/EnumCase.swift create mode 100644 Sources/SyntaxKit/ExprCodeBlock.swift create mode 100644 Sources/SyntaxKit/Fallthrough.swift create mode 100644 Sources/SyntaxKit/For.swift create mode 100644 Sources/SyntaxKit/Guard.swift create mode 100644 Sources/SyntaxKit/Literal+Convenience.swift create mode 100644 Sources/SyntaxKit/Literal+ExprCodeBlock.swift create mode 100644 Sources/SyntaxKit/LiteralValue.swift create mode 100644 Sources/SyntaxKit/PatternConvertible.swift create mode 100644 Sources/SyntaxKit/SwitchLet.swift create mode 100644 Sources/SyntaxKit/Then.swift create mode 100644 Sources/SyntaxKit/TupleLiteral.swift create mode 100644 Sources/SyntaxKit/TuplePattern.swift create mode 100644 Sources/SyntaxKit/TuplePatternCodeBlock.swift create mode 100644 Sources/SyntaxKit/Variable+Initializers.swift create mode 100644 Sources/SyntaxKit/While.swift create mode 100644 Sources/SyntaxKit/parser/SourceRange.swift create mode 100644 Sources/SyntaxKit/parser/String+Extensions.swift create mode 100644 Sources/SyntaxKit/parser/StructureProperty.swift create mode 100644 Sources/SyntaxKit/parser/StructureValue.swift create mode 100644 Sources/SyntaxKit/parser/SyntaxType.swift create mode 100644 Sources/SyntaxKit/parser/Token.swift create mode 100644 Tests/SyntaxKitTests/Integration/.swiftlint.yml rename Tests/SyntaxKitTests/{BasicTests.swift => Integration/BlackjackCardTests.swift} (77%) rename Tests/SyntaxKitTests/{ => Integration}/BlackjackTests.swift (72%) rename Tests/SyntaxKitTests/{ => Integration}/CommentTests.swift (97%) create mode 100644 Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift create mode 100644 Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift create mode 100644 Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift rename Tests/SyntaxKitTests/{ => Unit}/AssertionMigrationTests.swift (95%) rename Tests/SyntaxKitTests/{ => Unit}/AttributeTests.swift (100%) create mode 100644 Tests/SyntaxKitTests/Unit/CallTests.swift rename Tests/SyntaxKitTests/{ => Unit}/ClassTests.swift (80%) rename Tests/SyntaxKitTests/{ => Unit}/CodeStyleMigrationTests.swift (97%) create mode 100644 Tests/SyntaxKitTests/Unit/ConditionalsTests.swift rename Tests/SyntaxKitTests/{ => Unit}/EdgeCaseTests.swift (97%) rename Tests/SyntaxKitTests/{ => Unit}/ExtensionTests.swift (88%) create mode 100644 Tests/SyntaxKitTests/Unit/ForLoopTests.swift rename Tests/SyntaxKitTests/{ => Unit}/FrameworkCompatibilityTests.swift (96%) rename Tests/SyntaxKitTests/{ => Unit}/FunctionTests.swift (90%) rename Tests/SyntaxKitTests/{ => Unit}/LiteralTests.swift (100%) rename Tests/SyntaxKitTests/{ => Unit}/LiteralValueTests.swift (51%) rename Tests/SyntaxKitTests/{ => Unit}/MainApplicationTests.swift (94%) rename Tests/SyntaxKitTests/{ => Unit}/MigrationTests.swift (95%) rename Tests/SyntaxKitTests/{ => Unit}/OptionsMacroIntegrationTests.swift (92%) create mode 100644 Tests/SyntaxKitTests/Unit/PatternConvertibleTests.swift rename Tests/SyntaxKitTests/{ => Unit}/ProtocolTests.swift (88%) rename Tests/SyntaxKitTests/{ => Unit}/String+Normalize.swift (79%) rename Tests/SyntaxKitTests/{ => Unit}/StructTests.swift (71%) rename Tests/SyntaxKitTests/{ => Unit}/TypeAliasTests.swift (96%) rename Tests/SyntaxKitTests/{ => Unit}/VariableStaticTests.swift (87%) diff --git a/.swiftlint.yml b/.swiftlint.yml index 6236845..8481cde 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -130,3 +130,4 @@ disabled_rules: - closure_parameter_position - trailing_comma - opening_brace + - optional_data_string_conversion diff --git a/Examples/Remaining/attributes/code.swift b/Examples/Completed/attributes/code.swift similarity index 100% rename from Examples/Remaining/attributes/code.swift rename to Examples/Completed/attributes/code.swift diff --git a/Examples/Remaining/attributes/dsl.swift b/Examples/Completed/attributes/dsl.swift similarity index 100% rename from Examples/Remaining/attributes/dsl.swift rename to Examples/Completed/attributes/dsl.swift diff --git a/Examples/Remaining/attributes/syntax.json b/Examples/Completed/attributes/syntax.json similarity index 100% rename from Examples/Remaining/attributes/syntax.json rename to Examples/Completed/attributes/syntax.json diff --git a/Examples/Completed/conditionals/code.swift b/Examples/Completed/conditionals/code.swift new file mode 100644 index 0000000..23b9ab1 --- /dev/null +++ b/Examples/Completed/conditionals/code.swift @@ -0,0 +1,154 @@ +// Simple if statement +let temperature = 25 +if temperature > 30 { + print("It's hot outside!") +} + +// If-else statement +let score = 85 +if score >= 90 { + print("Excellent!") +} else if score >= 80 { + print("Good job!") +} else if score >= 70 { + print("Passing") +} else { + print("Needs improvement") +} + +// MARK: - Optional Binding with If + +// Using if let for optional binding +let possibleNumber = "123" +if let actualNumber = Int(possibleNumber) { + print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)") +} else { + print("The string \"\(possibleNumber)\" could not be converted to an integer") +} + +// Multiple optional bindings +let possibleName: String? = "John" +let possibleAge: Int? = 30 +if let name = possibleName, let age = possibleAge { + print("\(name) is \(age) years old") +} + +// MARK: - Guard Statements +func greet(person: [String: String]) { + guard let name = person["name"] else { + print("No name provided") + return + } + + guard let age = person["age"], let ageInt = Int(age) else { + print("Invalid age provided") + return + } + + print("Hello \(name), you are \(ageInt) years old") +} + +// MARK: - Switch Statements +// Switch with range matching +let approximateCount = 62 +let countedThings = "moons orbiting Saturn" +let naturalCount: String +switch approximateCount { +case 0: + naturalCount = "no" +case 1..<5: + naturalCount = "a few" +case 5..<12: + naturalCount = "several" +case 12..<100: + naturalCount = "dozens of" +case 100..<1000: + naturalCount = "hundreds of" +default: + naturalCount = "many" +} +print("There are \(naturalCount) \(countedThings).") + +// Switch with tuple matching +let somePoint = (1, 1) +switch somePoint { +case (0, 0): + print("(0, 0) is at the origin") +case (_, 0): + print("(\(somePoint.0), 0) is on the x-axis") +case (0, _): + print("(0, \(somePoint.1)) is on the y-axis") +case (-2...2, -2...2): + print("(\(somePoint.0), \(somePoint.1)) is inside the box") +default: + print("(\(somePoint.0), \(somePoint.1)) is outside of the box") +} + +// Switch with value binding +let anotherPoint = (2, 0) +switch anotherPoint { +case (let x, 0): + print("on the x-axis with an x value of \(x)") +case (0, let y): + print("on the y-axis with a y value of \(y)") +case let (x, y): + print("somewhere else at (\(x), \(y))") +} + +// MARK: - Fallthrough +// Using fallthrough in switch +let integerToDescribe = 5 +var description = "The number \(integerToDescribe) is" +switch integerToDescribe { +case 2, 3, 5, 7, 11, 13, 17, 19: + description += " a prime number, and also" + fallthrough +default: + description += " an integer." +} +print(description) + +// MARK: - Labeled Statements +// Using labeled statements with break +let finalSquare = 25 +var board = [Int](repeating: 0, count: finalSquare + 1) +board[03] = 8 +board[06] = 11 +board[09] = 9 +board[10] = 2 +board[14] = -10 +board[19] = -11 +board[22] = -2 +board[24] = -8 + +var square = 0 +var diceRoll = 0 +while square != finalSquare { + diceRoll += 1 + if diceRoll == 7 { diceRoll = 1 } + switch square + diceRoll { + case finalSquare: + break + case let newSquare where newSquare > finalSquare: + continue + default: + square += diceRoll + square += board[square] + } +} + +// MARK: - For Loops +// For-in loop with enumerated() to get index and value +print("\n=== For-in with Enumerated ===") +for (index, name) in names.enumerated() { + print("\(index): \(name)") +} + +// For-in loop with where clause +print("\n=== For-in with Where Clause ===") +let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +for number in numbers where number % 2 == 0 { + print("Even number: \(number)") +} + + diff --git a/Examples/Completed/conditionals/dsl.swift b/Examples/Completed/conditionals/dsl.swift new file mode 100644 index 0000000..a666c2a --- /dev/null +++ b/Examples/Completed/conditionals/dsl.swift @@ -0,0 +1,222 @@ +Group { + Variable(.let, name: "temperature", equals: Literal.integer(25)) + .comment { + Line("Simple if statement") + } + If { + Infix("temperature", ">", 30) + } then: { + Call("print", "It's hot outside!") + } + Variable(.let, name: "score", equals: Literal.integer(85)) + .comment { + Line("If-else statement") + } + If { + Infix("score", ">=", 90) + } then: { + Call("print", "Excellent!") + } else: { + If { + Infix("score", ">=", 80) + } then: { + Call("print", "Good job!") + } + If { + Infix("score", ">=", 70) + } then: { + Call("print", "Passing") + } + Then { + Call("print", "Needs improvement") + } + } + + Variable(.let, name: "possibleNumber", equals: Literal.string("123")) + .comment { + Line("MARK: - Optional Binding with If") + Line("Using if let for optional binding") + } + If(Let("actualNumber", Init("Int") { + ParameterExp(name: "", value: "possibleNumber") + }), then: { + Call("print", "The string \"\\(possibleNumber)\" has an integer value of \\(actualNumber)") + }, else: { + Call("print", "The string \"\\(possibleNumber)\" could not be converted to an integer") + }) + + Variable(.let, name: "possibleName", type: "String?", equals: Literal.string("John")).withExplicitType() + .comment { + Line("Multiple optional bindings") + } + Variable(.let, name: "possibleAge", type: "Int?", equals: Literal.integer(30)).withExplicitType() + If { + Let("name", "possibleName") + Let("age", "possibleAge") + } then: { + Call("print", "\\(name) is \\(age) years old") + } + + Function("greet", parameters: [Parameter("person", type: "[String: String]")]) { + Guard { + Let("name", "person[\"name\"]") + } else: { + Call("print", "No name provided") + } + Guard { + Let("age", "person[\"age\"]") + Let("ageInt", Init("Int") { + ParameterExp(name: "", value: "age") + }) + } else: { + Call("print", "Invalid age provided") + } + Call("print", "Hello \\(name), you are \\(ageInt) years old") + } +}.comment { + Line("MARK: - Guard Statements") +} + +Variable(.let, name: "approximateCount", equals: Literal.integer(62)) + .comment { + Line("MARK: - Switch Statements") + Line("Switch with range matching") + } +Variable(.let, name: "countedThings", equals: Literal.string("moons orbiting Saturn")) +Variable(.let, name: "naturalCount", type: "String").withExplicitType() +Switch("approximateCount") { + SwitchCase(0) { + Assignment("naturalCount", Literal.string("no")) + } + SwitchCase(1..<5) { + Assignment("naturalCount", Literal.string("a few")) + } + SwitchCase(5..<12) { + Assignment("naturalCount", Literal.string("several")) + } + SwitchCase(12..<100) { + Assignment("naturalCount", Literal.string("dozens of")) + } + SwitchCase(100..<1000) { + Assignment("naturalCount", Literal.string("hundreds of")) + } + Default { + Assignment("naturalCount", Literal.string("many")) + } +} +Call("print", "There are \\(naturalCount) \\(countedThings).") +Variable(.let, name: "somePoint", type: "(Int, Int)", equals: VariableExp("(1, 1)"), explicitType: true) +.comment { + Line("Switch with tuple matching") +} +Switch("somePoint") { + SwitchCase(Tuple.pattern([0, 0])) { + Call("print", "(0, 0) is at the origin") + } + SwitchCase(Tuple.pattern([nil, 0])) { + Call("print", "(\(somePoint.0), 0) is on the x-axis") + } + SwitchCase(Tuple.pattern([0, nil])) { + Call("print", "(0, \(somePoint.1)) is on the y-axis") + } + SwitchCase(Tuple.pattern([(-2...2), (-2...2)])) { + Call("print", "(\(somePoint.0), \(somePoint.1)) is inside the box") + } + Default { + Call("print", "(\(somePoint.0), \(somePoint.1)) is outside of the box") + } +} +Variable(.let, name: "anotherPoint", type: "(Int, Int)", equals: VariableExp("(2, 0)"), explicitType: true) +.comment { + Line("Switch with value binding") +} +Switch("anotherPoint") { + SwitchCase(Tuple.pattern([.let("x"), 0])) { + Call("print", "on the x-axis with an x value of \(x)") + + } + SwitchCase(Tuple.pattern([0, .let("y")])) { + Call("print", "on the y-axis with a y value of \(y)") + + } + SwitchCase(Tuple.pattern([.let("x"), .let("y")])) { + Call("print", "somewhere else at (\(x), \(y))") + + } +} +Variable(.let, name: "integerToDescribe", equals: 5) +Variable(.var, name: "description", equals: "The number \(integerToDescribe) is") +Switch("integerToDescribe") { + SwitchCase(2, 3, 5, 7, 11, 13, 17, 19) { + PlusAssign("description", "a prime number, and also") + Fallthrough() + } + Default { + PlusAssign("description", "an integer.") + } +} +Call("print", "description") + +Variable(.let, name: "finalSquare", equals: 25) +Variable(.var, name: "board", equals: Literal.array(Array(repeating: Literal.integer(0), count: 26))) + +Infix("board[03]", "+=", 8) +Infix("board[06]", "+=", 11) +Infix("board[09]", "+=", 9) +Infix("board[10]", "+=", 2) +Infix("board[14]", "-=", 10) +Infix("board[19]", "-=", 11) +Infix("board[22]", "-=", 2) +Infix("board[24]", "-=", 8) + +Variable(.var, name: "square", equals: 0) +Variable(.var, name: "diceRoll", equals: 0) +While { + Infix("square", "!=", "finalSquare") +} then: { + Assignment("diceRoll", "+", 1) + If { + Infix("diceRoll", "==", 7) + } then: { + Assignment("diceRoll", 1) + } + Switch(Infix("square", "+", "diceRoll")) { + SwitchCase("finalSquare") { + Break() + } + SwitchCase(Infix("newSquare", ">", "finalSquare")) { + Continue() + } + Default { + Infix("square", "+=", "diceRoll") + Infix("square", "+=", "board[square]") + } + } +} + +Call("print", "\n=== For-in with Enumerated ===") +.comment { + Line("MARK: - For Loops") + Line("For-in loop with enumerated() to get index and value") +} +For { + Tuple.pattern([VariableExp("index"), VariableExp("name")]) +} in: { + VariableExp("names").call("enumerated") +} then: { + Call("print", "Index: \\(index), Name: \\(name)") +} + +Call("print", "\n=== For-in with Where Clause ===") +.comment { + Line("For-in loop with where clause") +} +For { + VariableExp("numbers") +} in: { + Literal.array([Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), Literal.integer(9), Literal.integer(10)]) +} where: { + Infix("number", "%", 2) +} then: { + Call("print", "Even number: \\(number)") +} diff --git a/Examples/Completed/conditionals/syntax.json b/Examples/Completed/conditionals/syntax.json new file mode 100644 index 0000000..a1dc6cc --- /dev/null +++ b/Examples/Completed/conditionals/syntax.json @@ -0,0 +1 @@ +[{"range":{"endColumn":1,"startRow":2,"startColumn":1,"endRow":155},"text":"SourceFile","type":"other","id":0,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeShebang"},{"value":{"text":"nil"},"name":"shebang"},{"value":{"text":"nil"},"name":"unexpectedBetweenShebangAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndEndOfFileToken"},{"value":{"text":"","kind":"endOfFile"},"name":"endOfFileToken"},{"value":{"text":"nil"},"name":"unexpectedAfterEndOfFileToken"}]},{"range":{"startColumn":1,"endColumn":2,"startRow":2,"endRow":152},"text":"CodeBlockItemList","type":"collection","id":1,"parent":0,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"41"}}]},{"range":{"startRow":2,"endColumn":21,"endRow":2,"startColumn":1},"text":"CodeBlockItem","type":"other","id":2,"parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"parent":2,"type":"decl","id":3,"range":{"startColumn":1,"endRow":2,"endColumn":21,"startRow":2},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"text":"VariableDecl"},{"parent":3,"type":"collection","id":4,"range":{"startRow":1,"endColumn":1,"endRow":1,"startColumn":1},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"text":"AttributeList"},{"parent":3,"type":"collection","id":5,"range":{"startColumn":1,"endRow":1,"startRow":1,"endColumn":1},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"text":"DeclModifierList"},{"structure":[],"range":{"endColumn":4,"startColumn":1,"endRow":2,"startRow":2},"text":"let","token":{"kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"\/\/␣<\/span>Simple␣<\/span>if␣<\/span>statement<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"parent":3,"id":6,"type":"other"},{"type":"collection","text":"PatternBindingList","range":{"startRow":2,"startColumn":5,"endRow":2,"endColumn":21},"id":7,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":3},{"type":"other","text":"PatternBinding","range":{"endColumn":21,"startRow":2,"startColumn":5,"endRow":2},"id":8,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":7},{"type":"pattern","text":"IdentifierPattern","range":{"endColumn":16,"endRow":2,"startColumn":5,"startRow":2},"id":9,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"temperature","kind":"identifier("temperature")"},"name":"identifier"},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"parent":8},{"structure":[],"range":{"endRow":2,"endColumn":16,"startRow":2,"startColumn":5},"text":"temperature","token":{"kind":"identifier("temperature")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":9,"id":10,"type":"other"},{"id":11,"type":"other","parent":8,"range":{"endRow":2,"endColumn":21,"startRow":2,"startColumn":17},"text":"InitializerClause","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}]},{"structure":[],"range":{"endColumn":18,"endRow":2,"startColumn":17,"startRow":2},"text":"=","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"equal"},"parent":11,"id":12,"type":"other"},{"id":13,"type":"expr","parent":11,"range":{"endColumn":21,"endRow":2,"startColumn":19,"startRow":2},"text":"IntegerLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"25","kind":"integerLiteral("25")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}]},{"structure":[],"range":{"startRow":2,"startColumn":19,"endRow":2,"endColumn":21},"text":"25","token":{"kind":"integerLiteral("25")","trailingTrivia":"","leadingTrivia":""},"parent":13,"id":14,"type":"other"},{"id":15,"type":"other","parent":1,"range":{"startRow":3,"startColumn":1,"endRow":5,"endColumn":2},"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"ExpressionStmtSyntax","value":{"text":"ExpressionStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"id":16,"type":"other","range":{"endColumn":2,"endRow":5,"startRow":3,"startColumn":1},"parent":15,"text":"ExpressionStmt","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IfExprSyntax"},"ref":"IfExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"id":17,"type":"expr","range":{"endRow":5,"startColumn":1,"startRow":3,"endColumn":2},"parent":16,"text":"IfExpr","structure":[{"name":"unexpectedBeforeIfKeyword","value":{"text":"nil"}},{"name":"ifKeyword","value":{"text":"if","kind":"keyword(SwiftSyntax.Keyword.if)"}},{"name":"unexpectedBetweenIfKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax"},{"name":"unexpectedBetweenConditionsAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedBetweenBodyAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenElseKeywordAndElseBody","value":{"text":"nil"}},{"name":"elseBody","value":{"text":"nil"}},{"name":"unexpectedAfterElseBody","value":{"text":"nil"}}]},{"structure":[],"range":{"startRow":3,"startColumn":1,"endRow":3,"endColumn":3},"text":"if","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.if)"},"parent":17,"id":18,"type":"other"},{"range":{"startRow":3,"startColumn":4,"endRow":3,"endColumn":20},"structure":[{"value":{"text":"ConditionElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":17,"text":"ConditionElementList","id":19},{"range":{"endRow":3,"endColumn":20,"startRow":3,"startColumn":4},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":19,"text":"ConditionElement","id":20},{"range":{"endColumn":20,"endRow":3,"startRow":3,"startColumn":4},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"type":"expr","parent":20,"text":"InfixOperatorExpr","id":21},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"temperature","kind":"identifier("temperature")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"endRow":3,"startColumn":4,"endColumn":15,"startRow":3},"text":"DeclReferenceExpr","type":"expr","id":22,"parent":21},{"structure":[],"range":{"startColumn":4,"endRow":3,"endColumn":15,"startRow":3},"text":"temperature","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"identifier("temperature")"},"parent":22,"id":23,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator(">")","text":">"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"range":{"startColumn":16,"endRow":3,"endColumn":17,"startRow":3},"text":"BinaryOperatorExpr","type":"expr","id":24,"parent":21},{"structure":[],"range":{"endColumn":17,"startRow":3,"startColumn":16,"endRow":3},"text":">","token":{"leadingTrivia":"","kind":"binaryOperator(">")","trailingTrivia":"␣<\/span>"},"parent":24,"id":25,"type":"other"},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("30")","text":"30"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"endColumn":20,"startRow":3,"startColumn":18,"endRow":3},"text":"IntegerLiteralExpr","type":"expr","id":26,"parent":21},{"structure":[],"range":{"startColumn":18,"startRow":3,"endRow":3,"endColumn":20},"text":"30","token":{"kind":"integerLiteral("30")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":26,"id":27,"type":"other"},{"type":"other","text":"CodeBlock","id":28,"parent":17,"range":{"startColumn":21,"endRow":5,"endColumn":2,"startRow":3},"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}]},{"structure":[],"range":{"endColumn":22,"startRow":3,"startColumn":21,"endRow":3},"text":"{","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"parent":28,"id":29,"type":"other"},{"type":"collection","text":"CodeBlockItemList","id":30,"parent":28,"range":{"endColumn":31,"startRow":4,"startColumn":5,"endRow":4},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","text":"CodeBlockItem","id":31,"parent":30,"range":{"endColumn":31,"endRow":4,"startRow":4,"startColumn":5},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"type":"expr","text":"FunctionCallExpr","id":32,"parent":31,"range":{"endColumn":31,"startRow":4,"endRow":4,"startColumn":5},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"id":33,"range":{"startRow":4,"startColumn":5,"endRow":4,"endColumn":10},"type":"expr","parent":32,"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"structure":[],"range":{"startRow":4,"endColumn":10,"startColumn":5,"endRow":4},"text":"print","token":{"kind":"identifier("print")","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":33,"id":34,"type":"other"},{"structure":[],"range":{"startRow":4,"endColumn":11,"startColumn":10,"endRow":4},"text":"(","token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"parent":32,"id":35,"type":"other"},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"LabeledExprList","parent":32,"range":{"startRow":4,"endColumn":30,"startColumn":11,"endRow":4},"id":36,"type":"collection"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"LabeledExpr","parent":36,"range":{"startRow":4,"startColumn":11,"endRow":4,"endColumn":30},"id":37,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments","ref":"StringLiteralSegmentListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"text":"StringLiteralExpr","parent":37,"range":{"startRow":4,"startColumn":11,"endRow":4,"endColumn":30},"id":38,"type":"expr"},{"structure":[],"range":{"endRow":4,"startRow":4,"startColumn":11,"endColumn":12},"text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"parent":38,"id":39,"type":"other"},{"parent":38,"type":"collection","text":"StringLiteralSegmentList","range":{"endRow":4,"startRow":4,"startColumn":12,"endColumn":29},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"id":40},{"parent":40,"type":"other","text":"StringSegment","range":{"startRow":4,"endRow":4,"startColumn":12,"endColumn":29},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"It's hot outside!","kind":"stringSegment("It\\'s hot outside!")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":41},{"structure":[],"range":{"startRow":4,"endRow":4,"endColumn":29,"startColumn":12},"text":"It's␣<\/span>hot␣<\/span>outside!","token":{"leadingTrivia":"","kind":"stringSegment("It\\'s hot outside!")","trailingTrivia":""},"parent":41,"id":42,"type":"other"},{"structure":[],"range":{"startRow":4,"endRow":4,"endColumn":30,"startColumn":29},"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"parent":38,"id":43,"type":"other"},{"structure":[],"range":{"startRow":4,"endRow":4,"endColumn":31,"startColumn":30},"text":")","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"parent":32,"id":44,"type":"other"},{"parent":32,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"MultipleTrailingClosureElementList","type":"collection","id":45,"range":{"startRow":4,"endRow":4,"endColumn":31,"startColumn":31}},{"structure":[],"range":{"startColumn":1,"endRow":5,"startRow":5,"endColumn":2},"text":"}","token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":""},"parent":28,"id":46,"type":"other"},{"parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","type":"other","id":47,"range":{"startColumn":1,"endRow":8,"startRow":8,"endColumn":15}},{"parent":47,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax","name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"text":"VariableDecl","type":"decl","id":48,"range":{"startRow":8,"endRow":8,"endColumn":15,"startColumn":1}},{"range":{"endRow":5,"endColumn":2,"startColumn":2,"startRow":5},"text":"AttributeList","id":49,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":48,"type":"collection"},{"range":{"startColumn":2,"endRow":5,"startRow":5,"endColumn":2},"text":"DeclModifierList","id":50,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":48,"type":"collection"},{"structure":[],"range":{"endColumn":4,"startColumn":1,"endRow":8,"startRow":8},"text":"let","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>If-else␣<\/span>statement<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"parent":48,"id":51,"type":"other"},{"range":{"endColumn":15,"startColumn":5,"endRow":8,"startRow":8},"text":"PatternBindingList","id":52,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":48,"type":"collection"},{"range":{"startRow":8,"endRow":8,"startColumn":5,"endColumn":15},"text":"PatternBinding","id":53,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"name":"initializer","ref":"InitializerClauseSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":52,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("score")","text":"score"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":54,"parent":53,"text":"IdentifierPattern","range":{"endRow":8,"endColumn":10,"startRow":8,"startColumn":5},"type":"pattern"},{"structure":[],"range":{"endRow":8,"startColumn":5,"endColumn":10,"startRow":8},"text":"score","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("score")","leadingTrivia":""},"parent":54,"id":55,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"name":"value","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":56,"parent":53,"text":"InitializerClause","range":{"endRow":8,"startColumn":11,"endColumn":15,"startRow":8},"type":"other"},{"structure":[],"range":{"startColumn":11,"endColumn":12,"startRow":8,"endRow":8},"text":"=","token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":56,"id":57,"type":"other"},{"range":{"startColumn":13,"endColumn":15,"startRow":8,"endRow":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"85","kind":"integerLiteral("85")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","parent":56,"text":"IntegerLiteralExpr","id":58},{"id":59,"range":{"startColumn":13,"endRow":8,"startRow":8,"endColumn":15},"structure":[],"parent":58,"text":"85","type":"other","token":{"leadingTrivia":"","kind":"integerLiteral("85")","trailingTrivia":""}},{"range":{"startColumn":1,"endRow":17,"startRow":9,"endColumn":2},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"ExpressionStmtSyntax"},"ref":"ExpressionStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","parent":1,"text":"CodeBlockItem","id":60},{"range":{"startRow":9,"startColumn":1,"endColumn":2,"endRow":17},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IfExprSyntax"},"name":"expression","ref":"IfExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"other","parent":60,"text":"ExpressionStmt","id":61},{"id":62,"structure":[{"name":"unexpectedBeforeIfKeyword","value":{"text":"nil"}},{"name":"ifKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.if)","text":"if"}},{"name":"unexpectedBetweenIfKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax"},{"name":"unexpectedBetweenConditionsAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedBetweenBodyAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndElseBody","value":{"text":"nil"}},{"name":"elseBody","value":{"text":"IfExprSyntax"},"ref":"IfExprSyntax"},{"name":"unexpectedAfterElseBody","value":{"text":"nil"}}],"type":"expr","parent":61,"text":"IfExpr","range":{"startColumn":1,"startRow":9,"endRow":17,"endColumn":2}},{"id":63,"range":{"startColumn":1,"endColumn":3,"startRow":9,"endRow":9},"structure":[],"parent":62,"text":"if","type":"other","token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.if)","trailingTrivia":"␣<\/span>"}},{"id":64,"structure":[{"value":{"text":"ConditionElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":62,"text":"ConditionElementList","range":{"startColumn":4,"endColumn":15,"startRow":9,"endRow":9}},{"id":65,"structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax","name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":64,"text":"ConditionElement","range":{"endColumn":15,"startRow":9,"startColumn":4,"endRow":9}},{"text":"InfixOperatorExpr","type":"expr","id":66,"range":{"startColumn":4,"endRow":9,"startRow":9,"endColumn":15},"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"parent":65},{"text":"DeclReferenceExpr","type":"expr","id":67,"range":{"endColumn":9,"endRow":9,"startRow":9,"startColumn":4},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("score")","text":"score"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":66},{"id":68,"range":{"endColumn":9,"startRow":9,"endRow":9,"startColumn":4},"structure":[],"text":"score","parent":67,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("score")"}},{"range":{"endColumn":12,"startRow":9,"endRow":9,"startColumn":10},"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":">=","kind":"binaryOperator(">=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","text":"BinaryOperatorExpr","id":69,"parent":66},{"id":70,"range":{"startRow":9,"startColumn":10,"endColumn":12,"endRow":9},"structure":[],"text":">=","parent":69,"type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"binaryOperator(">=")"}},{"range":{"startRow":9,"startColumn":13,"endColumn":15,"endRow":9},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"90","kind":"integerLiteral("90")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":71,"parent":66},{"id":72,"range":{"startColumn":13,"startRow":9,"endRow":9,"endColumn":15},"structure":[],"text":"90","parent":71,"type":"other","token":{"kind":"integerLiteral("90")","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"startColumn":16,"startRow":9,"endRow":11,"endColumn":2},"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"type":"other","text":"CodeBlock","id":73,"parent":62},{"id":74,"range":{"startRow":9,"endColumn":17,"endRow":9,"startColumn":16},"parent":73,"structure":[],"text":"{","type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"}},{"parent":73,"id":75,"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","range":{"startRow":10,"endColumn":24,"endRow":10,"startColumn":5},"text":"CodeBlockItemList"},{"parent":75,"id":76,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","range":{"startColumn":5,"startRow":10,"endColumn":24,"endRow":10},"text":"CodeBlockItem"},{"parent":76,"id":77,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","range":{"endRow":10,"endColumn":24,"startRow":10,"startColumn":5},"text":"FunctionCallExpr"},{"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":77,"type":"expr","id":78,"range":{"startRow":10,"startColumn":5,"endRow":10,"endColumn":10}},{"id":79,"range":{"endRow":10,"startColumn":5,"endColumn":10,"startRow":10},"structure":[],"text":"print","parent":78,"type":"other","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""}},{"id":80,"range":{"endRow":10,"startColumn":10,"endColumn":11,"startRow":10},"structure":[],"text":"(","parent":77,"type":"other","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""}},{"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":77,"type":"collection","id":81,"range":{"endRow":10,"startColumn":11,"endColumn":23,"startRow":10}},{"range":{"startColumn":11,"endColumn":23,"endRow":10,"startRow":10},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":82,"text":"LabeledExpr","parent":81},{"range":{"endColumn":23,"startRow":10,"endRow":10,"startColumn":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"type":"expr","id":83,"text":"StringLiteralExpr","parent":82},{"id":84,"range":{"endColumn":12,"endRow":10,"startRow":10,"startColumn":11},"structure":[],"parent":83,"text":""","type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"}},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":83,"id":85,"text":"StringLiteralSegmentList","range":{"endColumn":22,"endRow":10,"startRow":10,"startColumn":12}},{"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("Excellent!")","text":"Excellent!"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","parent":85,"id":86,"text":"StringSegment","range":{"startColumn":12,"endRow":10,"startRow":10,"endColumn":22}},{"id":87,"range":{"endColumn":22,"endRow":10,"startColumn":12,"startRow":10},"structure":[],"parent":86,"text":"Excellent!","type":"other","token":{"kind":"stringSegment("Excellent!")","leadingTrivia":"","trailingTrivia":""}},{"id":88,"range":{"endColumn":23,"endRow":10,"startColumn":22,"startRow":10},"structure":[],"parent":83,"text":""","type":"other","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""}},{"id":89,"range":{"endColumn":24,"endRow":10,"startColumn":23,"startRow":10},"structure":[],"parent":77,"text":")","type":"other","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""}},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","parent":77,"id":90,"text":"MultipleTrailingClosureElementList","range":{"endColumn":24,"endRow":10,"startColumn":24,"startRow":10}},{"id":91,"range":{"endRow":11,"startRow":11,"startColumn":1,"endColumn":2},"parent":73,"text":"}","structure":[],"type":"other","token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>"}},{"id":92,"range":{"endRow":11,"startRow":11,"startColumn":3,"endColumn":7},"parent":62,"text":"else","structure":[],"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.else)","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"id":93,"type":"expr","text":"IfExpr","range":{"endRow":17,"startRow":11,"startColumn":8,"endColumn":2},"parent":62,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIfKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.if)","text":"if"},"name":"ifKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenIfKeywordAndConditions"},{"value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax","name":"conditions"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionsAndBody"},{"value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax","name":"body"},{"value":{"text":"nil"},"name":"unexpectedBetweenBodyAndElseKeyword"},{"value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"},"name":"elseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenElseKeywordAndElseBody"},{"value":{"text":"IfExprSyntax"},"ref":"IfExprSyntax","name":"elseBody"},{"value":{"text":"nil"},"name":"unexpectedAfterElseBody"}]},{"id":94,"range":{"startColumn":8,"endRow":11,"endColumn":10,"startRow":11},"parent":93,"text":"if","structure":[],"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.if)","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"id":95,"type":"collection","text":"ConditionElementList","range":{"startColumn":11,"endRow":11,"endColumn":22,"startRow":11},"parent":93,"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"parent":95,"text":"ConditionElement","id":96,"type":"other","range":{"startRow":11,"endColumn":22,"endRow":11,"startColumn":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"condition","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"parent":96,"text":"InfixOperatorExpr","id":97,"type":"expr","range":{"startRow":11,"startColumn":11,"endRow":11,"endColumn":22},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}]},{"parent":97,"text":"DeclReferenceExpr","id":98,"type":"expr","range":{"startColumn":11,"endColumn":16,"startRow":11,"endRow":11},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"score","kind":"identifier("score")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"id":99,"range":{"startRow":11,"startColumn":11,"endRow":11,"endColumn":16},"structure":[],"parent":98,"text":"score","type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("score")","leadingTrivia":""}},{"id":100,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":">=","kind":"binaryOperator(">=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"parent":97,"text":"BinaryOperatorExpr","type":"expr","range":{"startRow":11,"startColumn":17,"endRow":11,"endColumn":19}},{"id":101,"range":{"endRow":11,"endColumn":19,"startRow":11,"startColumn":17},"structure":[],"parent":100,"text":">=","type":"other","token":{"kind":"binaryOperator(">=")","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"id":102,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"80","kind":"integerLiteral("80")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"parent":97,"text":"IntegerLiteralExpr","type":"expr","range":{"endRow":11,"endColumn":22,"startRow":11,"startColumn":20}},{"id":103,"range":{"endRow":11,"startRow":11,"startColumn":20,"endColumn":22},"structure":[],"parent":102,"text":"80","type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"integerLiteral("80")"}},{"id":104,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":93,"text":"CodeBlock","type":"other","range":{"endRow":13,"startRow":11,"startColumn":23,"endColumn":2}},{"id":105,"range":{"endColumn":24,"startColumn":23,"startRow":11,"endRow":11},"parent":104,"text":"{","structure":[],"type":"other","token":{"leadingTrivia":"","kind":"leftBrace","trailingTrivia":""}},{"type":"collection","range":{"endColumn":23,"startColumn":5,"startRow":12,"endRow":12},"parent":104,"text":"CodeBlockItemList","id":106,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","range":{"startRow":12,"startColumn":5,"endRow":12,"endColumn":23},"parent":106,"text":"CodeBlockItem","id":107,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"type":"expr","range":{"startColumn":5,"endRow":12,"startRow":12,"endColumn":23},"parent":107,"text":"FunctionCallExpr","id":108,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"id":109,"type":"expr","parent":108,"range":{"startColumn":5,"startRow":12,"endColumn":10,"endRow":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"text":"DeclReferenceExpr"},{"id":110,"range":{"endRow":12,"endColumn":10,"startColumn":5,"startRow":12},"parent":109,"structure":[],"text":"print","type":"other","token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")"}},{"id":111,"range":{"endRow":12,"endColumn":11,"startColumn":10,"startRow":12},"structure":[],"text":"(","parent":108,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"}},{"parent":108,"text":"LabeledExprList","range":{"endRow":12,"endColumn":22,"startRow":12,"startColumn":11},"id":112,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"parent":112,"text":"LabeledExpr","range":{"startRow":12,"endColumn":22,"endRow":12,"startColumn":11},"id":113,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"parent":113,"text":"StringLiteralExpr","range":{"endRow":12,"endColumn":22,"startColumn":11,"startRow":12},"id":114,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr"},{"id":115,"type":"other","text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"structure":[],"parent":114,"range":{"startColumn":11,"endColumn":12,"startRow":12,"endRow":12}},{"id":116,"type":"collection","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"text":"StringLiteralSegmentList","parent":114,"range":{"startColumn":12,"endColumn":21,"startRow":12,"endRow":12}},{"id":117,"type":"other","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Good job!","kind":"stringSegment("Good job!")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment","parent":116,"range":{"startRow":12,"endRow":12,"startColumn":12,"endColumn":21}},{"id":118,"type":"other","text":"Good␣<\/span>job!","token":{"kind":"stringSegment("Good job!")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":117,"range":{"startColumn":12,"endRow":12,"endColumn":21,"startRow":12}},{"id":119,"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":114,"range":{"startColumn":21,"endRow":12,"endColumn":22,"startRow":12}},{"id":120,"text":")","type":"other","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":108,"range":{"startRow":12,"startColumn":22,"endColumn":23,"endRow":12}},{"parent":108,"range":{"endRow":12,"startRow":12,"endColumn":23,"startColumn":23},"type":"collection","id":121,"text":"MultipleTrailingClosureElementList","structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"id":122,"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"rightBrace"},"structure":[],"parent":104,"range":{"startRow":13,"startColumn":1,"endColumn":2,"endRow":13}},{"id":123,"type":"other","text":"else","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.else)"},"structure":[],"parent":93,"range":{"startRow":13,"startColumn":3,"endColumn":7,"endRow":13}},{"parent":93,"range":{"startRow":13,"startColumn":8,"endColumn":2,"endRow":17},"type":"expr","id":124,"text":"IfExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIfKeyword"},{"value":{"text":"if","kind":"keyword(SwiftSyntax.Keyword.if)"},"name":"ifKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenIfKeywordAndConditions"},{"value":{"text":"ConditionElementListSyntax"},"name":"conditions","ref":"ConditionElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionsAndBody"},{"value":{"text":"CodeBlockSyntax"},"name":"body","ref":"CodeBlockSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBodyAndElseKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.else)","text":"else"},"name":"elseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenElseKeywordAndElseBody"},{"value":{"text":"CodeBlockSyntax"},"name":"elseBody","ref":"CodeBlockSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterElseBody"}]},{"id":125,"type":"other","text":"if","token":{"kind":"keyword(SwiftSyntax.Keyword.if)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"parent":124,"range":{"endRow":13,"endColumn":10,"startColumn":8,"startRow":13}},{"range":{"startRow":13,"startColumn":11,"endColumn":22,"endRow":13},"type":"collection","structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":126,"text":"ConditionElementList","parent":124},{"range":{"startRow":13,"startColumn":11,"endColumn":22,"endRow":13},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":127,"text":"ConditionElement","parent":126},{"range":{"startRow":13,"endRow":13,"startColumn":11,"endColumn":22},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"id":128,"text":"InfixOperatorExpr","parent":127},{"range":{"endRow":13,"endColumn":16,"startRow":13,"startColumn":11},"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("score")","text":"score"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":129,"text":"DeclReferenceExpr","parent":128},{"id":130,"text":"score","type":"other","token":{"leadingTrivia":"","kind":"identifier("score")","trailingTrivia":"␣<\/span>"},"structure":[],"parent":129,"range":{"endRow":13,"startColumn":11,"startRow":13,"endColumn":16}},{"text":"BinaryOperatorExpr","range":{"endRow":13,"startColumn":17,"startRow":13,"endColumn":19},"id":131,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator(">=")","text":">="},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"type":"expr","parent":128},{"id":132,"text":">=","type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"binaryOperator(">=")","leadingTrivia":""},"structure":[],"parent":131,"range":{"endColumn":19,"startRow":13,"startColumn":17,"endRow":13}},{"text":"IntegerLiteralExpr","range":{"endColumn":22,"startRow":13,"startColumn":20,"endRow":13},"id":133,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"70","kind":"integerLiteral("70")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","parent":128},{"id":134,"text":"70","type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"integerLiteral("70")"},"structure":[],"parent":133,"range":{"startRow":13,"endRow":13,"endColumn":22,"startColumn":20}},{"text":"CodeBlock","range":{"startRow":13,"endRow":15,"endColumn":2,"startColumn":23},"id":135,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","parent":124},{"id":136,"text":"{","type":"other","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":135,"range":{"endColumn":24,"startColumn":23,"startRow":13,"endRow":13}},{"id":137,"text":"CodeBlockItemList","range":{"endColumn":21,"startColumn":5,"startRow":14,"endRow":14},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":135},{"id":138,"text":"CodeBlockItem","range":{"endColumn":21,"startRow":14,"startColumn":5,"endRow":14},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","parent":137},{"id":139,"text":"FunctionCallExpr","range":{"startRow":14,"endColumn":21,"endRow":14,"startColumn":5},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","parent":138},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":140,"parent":139,"text":"DeclReferenceExpr","type":"expr","range":{"startRow":14,"startColumn":5,"endColumn":10,"endRow":14}},{"id":141,"text":"print","type":"other","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"structure":[],"parent":140,"range":{"endRow":14,"endColumn":10,"startRow":14,"startColumn":5}},{"id":142,"type":"other","text":"(","token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"structure":[],"parent":139,"range":{"startRow":14,"endColumn":11,"startColumn":10,"endRow":14}},{"type":"collection","text":"LabeledExprList","parent":139,"range":{"startRow":14,"endColumn":20,"startColumn":11,"endRow":14},"id":143,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","text":"LabeledExpr","parent":143,"range":{"startRow":14,"startColumn":11,"endColumn":20,"endRow":14},"id":144,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"type":"expr","text":"StringLiteralExpr","parent":144,"range":{"startRow":14,"startColumn":11,"endRow":14,"endColumn":20},"id":145,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}]},{"id":146,"text":""","type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"structure":[],"parent":145,"range":{"endColumn":12,"startColumn":11,"startRow":14,"endRow":14}},{"range":{"endColumn":19,"startColumn":12,"startRow":14,"endRow":14},"parent":145,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"StringLiteralSegmentList","type":"collection","id":147},{"range":{"startRow":14,"endRow":14,"startColumn":12,"endColumn":19},"parent":147,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("Passing")","text":"Passing"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment","type":"other","id":148},{"id":149,"text":"Passing","type":"other","token":{"kind":"stringSegment("Passing")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":148,"range":{"endRow":14,"endColumn":19,"startRow":14,"startColumn":12}},{"id":150,"type":"other","text":""","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"structure":[],"parent":145,"range":{"startColumn":19,"startRow":14,"endRow":14,"endColumn":20}},{"id":151,"type":"other","text":")","token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"structure":[],"parent":139,"range":{"startColumn":20,"startRow":14,"endRow":14,"endColumn":21}},{"range":{"startColumn":21,"startRow":14,"endRow":14,"endColumn":21},"type":"collection","parent":139,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"MultipleTrailingClosureElementList","id":152},{"id":153,"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"rightBrace"},"structure":[],"parent":135,"range":{"startRow":15,"endRow":15,"startColumn":1,"endColumn":2}},{"id":154,"type":"other","text":"else","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.else)"},"structure":[],"parent":124,"range":{"startRow":15,"endRow":15,"startColumn":3,"endColumn":7}},{"range":{"startRow":15,"endRow":17,"startColumn":8,"endColumn":2},"type":"other","parent":124,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"text":"CodeBlock","id":155},{"id":156,"type":"other","text":"{","token":{"trailingTrivia":"","kind":"leftBrace","leadingTrivia":""},"structure":[],"parent":155,"range":{"startRow":15,"endColumn":9,"startColumn":8,"endRow":15}},{"range":{"startRow":16,"endColumn":31,"startColumn":5,"endRow":16},"type":"collection","parent":155,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"text":"CodeBlockItemList","id":157},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","id":158,"parent":157,"text":"CodeBlockItem","range":{"endRow":16,"startRow":16,"endColumn":31,"startColumn":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","id":159,"parent":158,"text":"FunctionCallExpr","range":{"endRow":16,"startRow":16,"startColumn":5,"endColumn":31}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":159,"type":"expr","id":160,"text":"DeclReferenceExpr","range":{"endColumn":10,"startColumn":5,"startRow":16,"endRow":16}},{"id":161,"type":"other","text":"print","token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"parent":160,"range":{"endRow":16,"startRow":16,"startColumn":5,"endColumn":10}},{"text":"(","range":{"endRow":16,"startRow":16,"startColumn":10,"endColumn":11},"parent":159,"type":"other","id":162,"structure":[],"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""}},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":159,"type":"collection","id":163,"text":"LabeledExprList","range":{"endRow":16,"startRow":16,"startColumn":11,"endColumn":30}},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"expression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":163,"type":"other","id":164,"text":"LabeledExpr","range":{"endColumn":30,"startColumn":11,"startRow":16,"endRow":16}},{"range":{"endRow":16,"startColumn":11,"endColumn":30,"startRow":16},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","id":165,"parent":164,"text":"StringLiteralExpr"},{"text":""","range":{"endRow":16,"endColumn":12,"startRow":16,"startColumn":11},"parent":165,"type":"other","id":166,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"}},{"id":167,"range":{"endColumn":29,"startRow":16,"startColumn":12,"endRow":16},"parent":165,"text":"StringLiteralSegmentList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"id":168,"range":{"endColumn":29,"startColumn":12,"endRow":16,"startRow":16},"parent":167,"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Needs improvement","kind":"stringSegment("Needs improvement")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other"},{"text":"Needs␣<\/span>improvement","range":{"startRow":16,"startColumn":12,"endColumn":29,"endRow":16},"parent":168,"type":"other","id":169,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Needs improvement")"}},{"text":""","range":{"startRow":16,"startColumn":29,"endColumn":30,"endRow":16},"parent":165,"type":"other","id":170,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"}},{"text":")","range":{"startRow":16,"startColumn":30,"endColumn":31,"endRow":16},"parent":159,"type":"other","id":171,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"}},{"id":172,"range":{"startRow":16,"startColumn":31,"endColumn":31,"endRow":16},"parent":159,"text":"MultipleTrailingClosureElementList","structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection"},{"text":"}","range":{"startColumn":1,"startRow":17,"endRow":17,"endColumn":2},"parent":155,"type":"other","id":173,"structure":[],"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"}},{"id":174,"range":{"startColumn":1,"startRow":22,"endRow":22,"endColumn":27},"parent":1,"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other"},{"id":175,"range":{"endRow":22,"endColumn":27,"startColumn":1,"startRow":22},"text":"VariableDecl","parent":174,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"type":"decl"},{"id":176,"range":{"endRow":17,"startRow":17,"endColumn":2,"startColumn":2},"text":"AttributeList","parent":175,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection"},{"id":177,"range":{"startColumn":2,"endRow":17,"endColumn":2,"startRow":17},"text":"DeclModifierList","parent":175,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection"},{"text":"let","range":{"endRow":22,"endColumn":4,"startRow":22,"startColumn":1},"parent":175,"type":"other","id":178,"structure":[],"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Optional␣<\/span>Binding␣<\/span>with␣<\/span>If<\/span>↲<\/span>↲<\/span>\/\/␣<\/span>Using␣<\/span>if␣<\/span>let␣<\/span>for␣<\/span>optional␣<\/span>binding<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"type":"collection","range":{"endRow":22,"endColumn":27,"startRow":22,"startColumn":5},"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":179,"text":"PatternBindingList","parent":175},{"type":"other","range":{"startColumn":5,"endColumn":27,"startRow":22,"endRow":22},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":180,"text":"PatternBinding","parent":179},{"type":"pattern","range":{"startColumn":5,"endColumn":19,"startRow":22,"endRow":22},"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"value":{"kind":"identifier("possibleNumber")","text":"possibleNumber"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":181,"text":"IdentifierPattern","parent":180},{"text":"possibleNumber","range":{"endColumn":19,"endRow":22,"startColumn":5,"startRow":22},"parent":181,"type":"other","id":182,"structure":[],"token":{"kind":"identifier("possibleNumber")","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"range":{"endColumn":27,"endRow":22,"startColumn":20,"startRow":22},"parent":180,"type":"other","id":183,"text":"InitializerClause"},{"text":"=","range":{"endRow":22,"endColumn":21,"startColumn":20,"startRow":22},"parent":183,"type":"other","id":184,"structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""}},{"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"range":{"endRow":22,"endColumn":27,"startColumn":22,"startRow":22},"parent":183,"type":"expr","id":185,"text":"StringLiteralExpr"},{"text":""","range":{"endRow":22,"startColumn":22,"endColumn":23,"startRow":22},"parent":185,"type":"other","id":186,"structure":[],"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""}},{"parent":185,"range":{"endRow":22,"startColumn":23,"endColumn":26,"startRow":22},"text":"StringLiteralSegmentList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","id":187},{"parent":187,"range":{"startColumn":23,"endColumn":26,"endRow":22,"startRow":22},"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"123","kind":"stringSegment("123")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","id":188},{"text":"123","range":{"startColumn":23,"startRow":22,"endRow":22,"endColumn":26},"parent":188,"type":"other","id":189,"structure":[],"token":{"kind":"stringSegment("123")","leadingTrivia":"","trailingTrivia":""}},{"text":""","range":{"startColumn":26,"startRow":22,"endRow":22,"endColumn":27},"parent":185,"type":"other","id":190,"structure":[],"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""}},{"parent":1,"range":{"startColumn":1,"startRow":23,"endRow":27,"endColumn":2},"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ExpressionStmtSyntax","value":{"text":"ExpressionStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","id":191},{"range":{"endRow":27,"startColumn":1,"startRow":23,"endColumn":2},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IfExprSyntax"},"ref":"IfExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"other","parent":191,"text":"ExpressionStmt","id":192},{"range":{"startRow":23,"startColumn":1,"endRow":27,"endColumn":2},"structure":[{"name":"unexpectedBeforeIfKeyword","value":{"text":"nil"}},{"name":"ifKeyword","value":{"text":"if","kind":"keyword(SwiftSyntax.Keyword.if)"}},{"name":"unexpectedBetweenIfKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","ref":"ConditionElementListSyntax","value":{"text":"ConditionElementListSyntax"}},{"name":"unexpectedBetweenConditionsAndBody","value":{"text":"nil"}},{"name":"body","ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedBetweenBodyAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndElseBody","value":{"text":"nil"}},{"name":"elseBody","ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterElseBody","value":{"text":"nil"}}],"type":"expr","parent":192,"text":"IfExpr","id":193},{"text":"if","range":{"endColumn":3,"startColumn":1,"endRow":23,"startRow":23},"parent":193,"type":"other","id":194,"structure":[],"token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.if)","trailingTrivia":"␣<\/span>"}},{"text":"ConditionElementList","structure":[{"value":{"text":"ConditionElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":193,"range":{"endColumn":42,"startColumn":4,"endRow":23,"startRow":23},"type":"collection","id":195},{"text":"ConditionElement","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"ref":"OptionalBindingConditionSyntax","value":{"text":"OptionalBindingConditionSyntax"},"name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":195,"range":{"endRow":23,"endColumn":42,"startRow":23,"startColumn":4},"type":"other","id":196},{"text":"OptionalBindingCondition","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndPattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"name":"initializer","ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedAfterInitializer","value":{"text":"nil"}}],"parent":196,"range":{"endColumn":42,"startRow":23,"endRow":23,"startColumn":4},"type":"other","id":197},{"text":"let","range":{"startRow":23,"startColumn":4,"endRow":23,"endColumn":7},"parent":197,"type":"other","id":198,"structure":[],"token":{"kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"startRow":23,"startColumn":8,"endRow":23,"endColumn":20},"parent":197,"text":"IdentifierPattern","id":199,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("actualNumber")","text":"actualNumber"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"type":"pattern"},{"text":"actualNumber","range":{"endColumn":20,"startRow":23,"startColumn":8,"endRow":23},"parent":199,"type":"other","id":200,"structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("actualNumber")","leadingTrivia":""}},{"range":{"endColumn":42,"startRow":23,"startColumn":21,"endRow":23},"parent":197,"text":"InitializerClause","id":201,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"value","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"type":"other"},{"text":"=","range":{"endRow":23,"endColumn":22,"startRow":23,"startColumn":21},"parent":201,"type":"other","id":202,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"}},{"range":{"endRow":23,"endColumn":42,"startRow":23,"startColumn":23},"parent":201,"text":"FunctionCallExpr","id":203,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr"},{"parent":203,"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"Int","kind":"identifier("Int")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","range":{"startRow":23,"endRow":23,"startColumn":23,"endColumn":26},"id":204},{"text":"Int","range":{"startRow":23,"endRow":23,"startColumn":23,"endColumn":26},"parent":204,"type":"other","id":205,"structure":[],"token":{"trailingTrivia":"","kind":"identifier("Int")","leadingTrivia":""}},{"text":"(","range":{"endColumn":27,"startColumn":26,"endRow":23,"startRow":23},"parent":203,"type":"other","id":206,"structure":[],"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""}},{"type":"collection","range":{"endColumn":41,"startColumn":27,"endRow":23,"startRow":23},"id":207,"parent":203,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","range":{"endColumn":41,"endRow":23,"startColumn":27,"startRow":23},"id":208,"parent":207,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"type":"expr","range":{"endRow":23,"startRow":23,"startColumn":27,"endColumn":41},"id":209,"parent":208,"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"possibleNumber","kind":"identifier("possibleNumber")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"possibleNumber","range":{"startColumn":27,"endRow":23,"startRow":23,"endColumn":41},"parent":209,"type":"other","id":210,"structure":[],"token":{"kind":"identifier("possibleNumber")","trailingTrivia":"","leadingTrivia":""}},{"text":")","range":{"startColumn":41,"endRow":23,"startRow":23,"endColumn":42},"parent":203,"type":"other","id":211,"structure":[],"token":{"kind":"rightParen","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"startColumn":43,"endRow":23,"startRow":23,"endColumn":43},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":203,"type":"collection","id":212,"text":"MultipleTrailingClosureElementList"},{"range":{"startColumn":43,"endRow":25,"startRow":23,"endColumn":2},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":193,"type":"other","id":213,"text":"CodeBlock"},{"text":"{","range":{"startColumn":43,"endRow":23,"endColumn":44,"startRow":23},"parent":213,"type":"other","id":214,"structure":[],"token":{"trailingTrivia":"","kind":"leftBrace","leadingTrivia":""}},{"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":213,"type":"collection","id":215,"range":{"endColumn":86,"startRow":24,"startColumn":5,"endRow":24},"text":"CodeBlockItemList"},{"parent":215,"text":"CodeBlockItem","range":{"startRow":24,"startColumn":5,"endRow":24,"endColumn":86},"type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":216},{"parent":216,"text":"FunctionCallExpr","range":{"startRow":24,"startColumn":5,"endRow":24,"endColumn":86},"type":"expr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":217},{"id":218,"parent":217,"range":{"startRow":24,"startColumn":5,"endRow":24,"endColumn":10},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","text":"DeclReferenceExpr"},{"range":{"startRow":24,"startColumn":5,"endRow":24,"endColumn":10},"id":219,"structure":[],"type":"other","text":"print","parent":218,"token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")"}},{"range":{"startRow":24,"startColumn":10,"endRow":24,"endColumn":11},"id":220,"structure":[],"type":"other","text":"(","parent":217,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"}},{"id":221,"parent":217,"range":{"startRow":24,"startColumn":11,"endRow":24,"endColumn":85},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","text":"LabeledExprList"},{"id":222,"parent":221,"range":{"endColumn":85,"startRow":24,"startColumn":11,"endRow":24},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","text":"LabeledExpr"},{"text":"StringLiteralExpr","type":"expr","parent":222,"range":{"startRow":24,"startColumn":11,"endColumn":85,"endRow":24},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":223},{"range":{"endRow":24,"startColumn":11,"endColumn":12,"startRow":24},"type":"other","id":224,"structure":[],"text":""","parent":223,"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""}},{"text":"StringLiteralSegmentList","type":"collection","id":225,"range":{"endRow":24,"startColumn":12,"endColumn":84,"startRow":24},"parent":223,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}]},{"text":"StringSegment","type":"other","id":226,"range":{"endColumn":25,"startRow":24,"startColumn":12,"endRow":24},"parent":225,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"The string \\"","kind":"stringSegment("The string \\\\\\"")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"range":{"endRow":24,"startRow":24,"endColumn":25,"startColumn":12},"type":"other","id":227,"structure":[],"text":"The␣<\/span>string␣<\/span>\\"","parent":226,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("The string \\\\\\"")"}},{"text":"ExpressionSegment","type":"other","id":228,"range":{"endRow":24,"startRow":24,"endColumn":42,"startColumn":25},"parent":225,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"range":{"startColumn":25,"endColumn":26,"endRow":24,"startRow":24},"structure":[],"type":"other","id":229,"text":"\\","parent":228,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"}},{"range":{"startColumn":26,"endColumn":27,"endRow":24,"startRow":24},"structure":[],"type":"other","id":230,"text":"(","parent":228,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"}},{"parent":228,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","range":{"startColumn":27,"endColumn":41,"endRow":24,"startRow":24},"id":231,"text":"LabeledExprList"},{"parent":231,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","range":{"startRow":24,"endColumn":41,"endRow":24,"startColumn":27},"id":232,"text":"LabeledExpr"},{"range":{"startRow":24,"endColumn":41,"startColumn":27,"endRow":24},"text":"DeclReferenceExpr","type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"possibleNumber","kind":"identifier("possibleNumber")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":232,"id":233},{"range":{"startColumn":27,"endRow":24,"endColumn":41,"startRow":24},"type":"other","structure":[],"id":234,"text":"possibleNumber","parent":233,"token":{"leadingTrivia":"","kind":"identifier("possibleNumber")","trailingTrivia":""}},{"range":{"startColumn":41,"endRow":24,"endColumn":42,"startRow":24},"type":"other","structure":[],"id":235,"text":")","parent":228,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""}},{"range":{"startColumn":42,"endRow":24,"endColumn":69,"startRow":24},"text":"StringSegment","type":"other","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("\\\\\\" has an integer value of ")","text":"\\" has an integer value of "}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"parent":225,"id":236},{"range":{"startColumn":42,"endColumn":69,"startRow":24,"endRow":24},"type":"other","structure":[],"id":237,"text":"\\"␣<\/span>has␣<\/span>an␣<\/span>integer␣<\/span>value␣<\/span>of␣<\/span>","parent":236,"token":{"kind":"stringSegment("\\\\\\" has an integer value of ")","leadingTrivia":"","trailingTrivia":""}},{"range":{"startColumn":69,"endColumn":84,"startRow":24,"endRow":24},"text":"ExpressionSegment","type":"other","structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"name":"expressions","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"parent":225,"id":238},{"range":{"endColumn":70,"startRow":24,"startColumn":69,"endRow":24},"structure":[],"type":"other","id":239,"text":"\\","parent":238,"token":{"kind":"backslash","trailingTrivia":"","leadingTrivia":""}},{"range":{"endColumn":71,"startRow":24,"startColumn":70,"endRow":24},"structure":[],"type":"other","id":240,"text":"(","parent":238,"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""}},{"text":"LabeledExprList","range":{"endColumn":83,"startRow":24,"startColumn":71,"endRow":24},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":238,"id":241},{"text":"LabeledExpr","range":{"endRow":24,"endColumn":83,"startRow":24,"startColumn":71},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":241,"id":242},{"text":"DeclReferenceExpr","id":243,"parent":242,"range":{"endRow":24,"endColumn":83,"startRow":24,"startColumn":71},"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("actualNumber")","text":"actualNumber"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"range":{"endRow":24,"startRow":24,"startColumn":71,"endColumn":83},"id":244,"type":"other","structure":[],"text":"actualNumber","parent":243,"token":{"kind":"identifier("actualNumber")","trailingTrivia":"","leadingTrivia":""}},{"range":{"endRow":24,"startRow":24,"startColumn":83,"endColumn":84},"id":245,"type":"other","structure":[],"text":")","parent":238,"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""}},{"text":"StringSegment","id":246,"parent":225,"range":{"endRow":24,"startRow":24,"startColumn":84,"endColumn":84},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"range":{"startColumn":84,"endRow":24,"endColumn":84,"startRow":24},"id":247,"type":"other","structure":[],"text":"","parent":246,"token":{"kind":"stringSegment("")","leadingTrivia":"","trailingTrivia":""}},{"range":{"startColumn":84,"startRow":24,"endColumn":85,"endRow":24},"id":248,"structure":[],"type":"other","text":""","parent":223,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""}},{"range":{"startColumn":85,"startRow":24,"endColumn":86,"endRow":24},"id":249,"structure":[],"type":"other","text":")","parent":217,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""}},{"parent":217,"id":250,"text":"MultipleTrailingClosureElementList","structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","range":{"startColumn":86,"startRow":24,"endColumn":86,"endRow":24}},{"range":{"startColumn":1,"startRow":25,"endRow":25,"endColumn":2},"id":251,"structure":[],"type":"other","text":"}","parent":213,"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>"}},{"range":{"startColumn":3,"startRow":25,"endRow":25,"endColumn":7},"id":252,"structure":[],"type":"other","text":"else","parent":193,"token":{"kind":"keyword(SwiftSyntax.Keyword.else)","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"parent":193,"id":253,"text":"CodeBlock","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","range":{"startColumn":8,"startRow":25,"endRow":27,"endColumn":2}},{"range":{"startRow":25,"endColumn":9,"startColumn":8,"endRow":25},"id":254,"structure":[],"type":"other","text":"{","parent":253,"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""}},{"parent":253,"id":255,"text":"CodeBlockItemList","structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","range":{"startRow":26,"endColumn":83,"startColumn":5,"endRow":26}},{"range":{"endColumn":83,"startRow":26,"endRow":26,"startColumn":5},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":255,"text":"CodeBlockItem","type":"other","id":256},{"range":{"endRow":26,"startRow":26,"startColumn":5,"endColumn":83},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"parent":256,"text":"FunctionCallExpr","type":"expr","id":257},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":258,"text":"DeclReferenceExpr","type":"expr","range":{"startRow":26,"endRow":26,"endColumn":10,"startColumn":5},"parent":257},{"range":{"endRow":26,"startRow":26,"endColumn":10,"startColumn":5},"structure":[],"id":259,"type":"other","text":"print","parent":258,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")","trailingTrivia":""}},{"range":{"endRow":26,"startRow":26,"endColumn":11,"startColumn":10},"structure":[],"id":260,"type":"other","text":"(","parent":257,"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""}},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":261,"text":"LabeledExprList","type":"collection","range":{"endRow":26,"startRow":26,"endColumn":82,"startColumn":11},"parent":257},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"expression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":262,"text":"LabeledExpr","type":"other","range":{"endRow":26,"endColumn":82,"startColumn":11,"startRow":26},"parent":261},{"type":"expr","id":263,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"text":"StringLiteralExpr","range":{"startRow":26,"endRow":26,"startColumn":11,"endColumn":82},"parent":262},{"parent":263,"type":"other","range":{"endColumn":12,"startRow":26,"endRow":26,"startColumn":11},"id":264,"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"""},{"parent":263,"id":265,"range":{"startRow":26,"startColumn":12,"endColumn":81,"endRow":26},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList"},{"parent":265,"id":266,"range":{"startColumn":12,"endRow":26,"endColumn":25,"startRow":26},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"The string \\"","kind":"stringSegment("The string \\\\\\"")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment"},{"parent":266,"range":{"endColumn":25,"startColumn":12,"startRow":26,"endRow":26},"type":"other","id":267,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("The string \\\\\\"")"},"structure":[],"text":"The␣<\/span>string␣<\/span>\\""},{"parent":265,"id":268,"range":{"endColumn":42,"startColumn":25,"startRow":26,"endRow":26},"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"type":"other","text":"ExpressionSegment"},{"parent":268,"range":{"startRow":26,"endRow":26,"endColumn":26,"startColumn":25},"type":"other","id":269,"token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"structure":[],"text":"\\"},{"parent":268,"range":{"startRow":26,"endRow":26,"endColumn":27,"startColumn":26},"type":"other","id":270,"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"structure":[],"text":"("},{"parent":268,"id":271,"range":{"startRow":26,"endRow":26,"endColumn":41,"startColumn":27},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList"},{"parent":271,"id":272,"range":{"startRow":26,"startColumn":27,"endColumn":41,"endRow":26},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr"},{"parent":272,"id":273,"range":{"endColumn":41,"startColumn":27,"startRow":26,"endRow":26},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"possibleNumber","kind":"identifier("possibleNumber")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr"},{"parent":273,"type":"other","range":{"startColumn":27,"endRow":26,"endColumn":41,"startRow":26},"id":274,"token":{"leadingTrivia":"","kind":"identifier("possibleNumber")","trailingTrivia":""},"text":"possibleNumber","structure":[]},{"parent":268,"type":"other","range":{"startColumn":41,"endRow":26,"endColumn":42,"startRow":26},"id":275,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"text":")","structure":[]},{"type":"other","parent":265,"text":"StringSegment","id":276,"range":{"startColumn":42,"endRow":26,"endColumn":81,"startRow":26},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"\\" could not be converted to an integer","kind":"stringSegment("\\\\\\" could not be converted to an integer")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"parent":276,"type":"other","range":{"startColumn":42,"endRow":26,"startRow":26,"endColumn":81},"id":277,"token":{"kind":"stringSegment("\\\\\\" could not be converted to an integer")","leadingTrivia":"","trailingTrivia":""},"text":"\\"␣<\/span>could␣<\/span>not␣<\/span>be␣<\/span>converted␣<\/span>to␣<\/span>an␣<\/span>integer","structure":[]},{"parent":263,"type":"other","range":{"startColumn":81,"endRow":26,"startRow":26,"endColumn":82},"id":278,"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"text":""","structure":[]},{"parent":257,"type":"other","range":{"startColumn":82,"endRow":26,"startRow":26,"endColumn":83},"id":279,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"text":")","structure":[]},{"type":"collection","parent":257,"text":"MultipleTrailingClosureElementList","id":280,"range":{"startColumn":83,"endRow":26,"startRow":26,"endColumn":83},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"parent":253,"type":"other","range":{"endColumn":2,"startRow":27,"endRow":27,"startColumn":1},"id":281,"token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>","kind":"rightBrace"},"text":"}","structure":[]},{"type":"other","parent":1,"id":282,"text":"CodeBlockItem","range":{"endRow":30,"startColumn":1,"endColumn":35,"startRow":30},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"type":"decl","parent":282,"id":283,"text":"VariableDecl","range":{"endColumn":35,"startColumn":1,"endRow":30,"startRow":30},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}]},{"type":"collection","parent":283,"id":284,"text":"AttributeList","range":{"startRow":27,"startColumn":2,"endRow":27,"endColumn":2},"structure":[{"value":{"text":"Element"},"name":"Element"},{"name":"Count","value":{"text":"0"}}]},{"range":{"startColumn":2,"startRow":27,"endRow":27,"endColumn":2},"type":"collection","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":283,"id":285,"text":"DeclModifierList"},{"parent":283,"range":{"startRow":30,"endColumn":4,"startColumn":1,"endRow":30},"type":"other","id":286,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>Multiple␣<\/span>optional␣<\/span>bindings<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"structure":[],"text":"let"},{"range":{"startRow":30,"endColumn":35,"startColumn":5,"endRow":30},"type":"collection","structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":283,"id":287,"text":"PatternBindingList"},{"range":{"endColumn":35,"startRow":30,"endRow":30,"startColumn":5},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation","ref":"TypeAnnotationSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"name":"initializer","ref":"InitializerClauseSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":287,"id":288,"text":"PatternBinding"},{"range":{"endColumn":17,"startRow":30,"endRow":30,"startColumn":5},"text":"IdentifierPattern","parent":288,"type":"pattern","id":289,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"possibleName","kind":"identifier("possibleName")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"parent":289,"range":{"startRow":30,"startColumn":5,"endRow":30,"endColumn":17},"type":"other","id":290,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("possibleName")"},"text":"possibleName","structure":[]},{"range":{"startRow":30,"startColumn":17,"endRow":30,"endColumn":26},"text":"TypeAnnotation","parent":288,"type":"other","id":291,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","value":{"text":"OptionalTypeSyntax"},"ref":"OptionalTypeSyntax"},{"name":"unexpectedAfterType","value":{"text":"nil"}}]},{"parent":291,"range":{"startColumn":17,"startRow":30,"endRow":30,"endColumn":18},"type":"other","id":292,"token":{"leadingTrivia":"","kind":"colon","trailingTrivia":"␣<\/span>"},"text":":","structure":[]},{"range":{"startColumn":19,"startRow":30,"endRow":30,"endColumn":26},"text":"OptionalType","parent":291,"type":"type","id":293,"structure":[{"name":"unexpectedBeforeWrappedType","value":{"text":"nil"}},{"ref":"IdentifierTypeSyntax","name":"wrappedType","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenWrappedTypeAndQuestionMark","value":{"text":"nil"}},{"value":{"text":"?","kind":"postfixQuestionMark"},"name":"questionMark"},{"value":{"text":"nil"},"name":"unexpectedAfterQuestionMark"}]},{"parent":293,"text":"IdentifierType","id":294,"range":{"endRow":30,"endColumn":25,"startRow":30,"startColumn":19},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("String")","text":"String"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"type":"type"},{"parent":294,"range":{"endRow":30,"endColumn":25,"startColumn":19,"startRow":30},"type":"other","id":295,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("String")"},"text":"String","structure":[]},{"parent":293,"range":{"endRow":30,"endColumn":26,"startColumn":25,"startRow":30},"type":"other","id":296,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"postfixQuestionMark"},"text":"?","structure":[]},{"parent":288,"text":"InitializerClause","id":297,"range":{"endRow":30,"endColumn":35,"startColumn":27,"startRow":30},"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"type":"other"},{"parent":297,"range":{"startRow":30,"endRow":30,"endColumn":28,"startColumn":27},"type":"other","id":298,"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"text":"=","structure":[]},{"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"type":"expr","parent":297,"id":299,"text":"StringLiteralExpr","range":{"endColumn":35,"startRow":30,"startColumn":29,"endRow":30}},{"parent":299,"type":"other","range":{"endColumn":30,"startRow":30,"startColumn":29,"endRow":30},"id":300,"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"structure":[],"text":"""},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":299,"id":301,"text":"StringLiteralSegmentList","range":{"endColumn":34,"startRow":30,"startColumn":30,"endRow":30}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("John")","text":"John"},"name":"content"},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","parent":301,"id":302,"text":"StringSegment","range":{"endRow":30,"startColumn":30,"endColumn":34,"startRow":30}},{"parent":302,"type":"other","range":{"startRow":30,"startColumn":30,"endColumn":34,"endRow":30},"id":303,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("John")"},"text":"John","structure":[]},{"parent":299,"type":"other","range":{"startRow":30,"startColumn":34,"endColumn":35,"endRow":30},"id":304,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","structure":[]},{"parent":1,"type":"other","id":305,"text":"CodeBlockItem","range":{"startRow":31,"startColumn":1,"endColumn":27,"endRow":31},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"VariableDeclSyntax","name":"item","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"parent":305,"type":"decl","id":306,"text":"VariableDecl","range":{"startColumn":1,"endRow":31,"endColumn":27,"startRow":31},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}]},{"type":"collection","text":"AttributeList","id":307,"parent":306,"range":{"startRow":30,"endRow":30,"startColumn":35,"endColumn":35},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}]},{"type":"collection","text":"DeclModifierList","id":308,"parent":306,"range":{"startColumn":35,"endColumn":35,"endRow":30,"startRow":30},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"parent":306,"type":"other","range":{"endRow":31,"startRow":31,"endColumn":4,"startColumn":1},"id":309,"token":{"kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>"},"text":"let","structure":[]},{"type":"collection","text":"PatternBindingList","id":310,"parent":306,"range":{"endRow":31,"startRow":31,"endColumn":27,"startColumn":5},"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","text":"PatternBinding","id":311,"parent":310,"range":{"endRow":31,"startColumn":5,"startRow":31,"endColumn":27},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation","ref":"TypeAnnotationSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"name":"initializer","ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"id":312,"parent":311,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("possibleAge")","text":"possibleAge"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"text":"IdentifierPattern","type":"pattern","range":{"startColumn":5,"endRow":31,"startRow":31,"endColumn":16}},{"parent":312,"type":"other","range":{"startColumn":5,"startRow":31,"endRow":31,"endColumn":16},"id":313,"token":{"kind":"identifier("possibleAge")","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"possibleAge"},{"id":314,"parent":311,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"ref":"OptionalTypeSyntax","name":"type","value":{"text":"OptionalTypeSyntax"}},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"text":"TypeAnnotation","type":"other","range":{"startColumn":16,"startRow":31,"endRow":31,"endColumn":22}},{"token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""},"text":":","structure":[],"id":315,"type":"other","range":{"endRow":31,"startRow":31,"startColumn":16,"endColumn":17},"parent":314},{"range":{"startRow":31,"endColumn":22,"startColumn":18,"endRow":31},"text":"OptionalType","type":"type","parent":314,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeWrappedType"},{"value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax","name":"wrappedType"},{"value":{"text":"nil"},"name":"unexpectedBetweenWrappedTypeAndQuestionMark"},{"value":{"kind":"postfixQuestionMark","text":"?"},"name":"questionMark"},{"value":{"text":"nil"},"name":"unexpectedAfterQuestionMark"}],"id":316},{"range":{"endRow":31,"endColumn":21,"startColumn":18,"startRow":31},"text":"IdentifierType","type":"type","parent":316,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("Int")","text":"Int"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":317},{"token":{"trailingTrivia":"","kind":"identifier("Int")","leadingTrivia":""},"text":"Int","structure":[],"range":{"endRow":31,"endColumn":21,"startRow":31,"startColumn":18},"type":"other","id":318,"parent":317},{"token":{"trailingTrivia":"␣<\/span>","kind":"postfixQuestionMark","leadingTrivia":""},"text":"?","structure":[],"range":{"endRow":31,"endColumn":22,"startRow":31,"startColumn":21},"type":"other","id":319,"parent":316},{"range":{"endRow":31,"endColumn":27,"startRow":31,"startColumn":23},"text":"InitializerClause","type":"other","parent":311,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"value"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":320},{"token":{"kind":"equal","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":"=","structure":[],"type":"other","range":{"startColumn":23,"startRow":31,"endRow":31,"endColumn":24},"id":321,"parent":320},{"text":"IntegerLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("30")","text":"30"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","range":{"startColumn":25,"startRow":31,"endRow":31,"endColumn":27},"id":322,"parent":320},{"token":{"trailingTrivia":"","kind":"integerLiteral("30")","leadingTrivia":""},"text":"30","structure":[],"type":"other","range":{"startColumn":25,"endRow":31,"endColumn":27,"startRow":31},"id":323,"parent":322},{"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ExpressionStmtSyntax"},"ref":"ExpressionStmtSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","range":{"startColumn":1,"endRow":34,"endColumn":2,"startRow":32},"id":324,"parent":1},{"text":"ExpressionStmt","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IfExprSyntax"},"ref":"IfExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"other","range":{"endColumn":2,"endRow":34,"startColumn":1,"startRow":32},"id":325,"parent":324},{"text":"IfExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIfKeyword"},{"value":{"text":"if","kind":"keyword(SwiftSyntax.Keyword.if)"},"name":"ifKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenIfKeywordAndConditions"},{"value":{"text":"ConditionElementListSyntax"},"name":"conditions","ref":"ConditionElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionsAndBody"},{"value":{"text":"CodeBlockSyntax"},"name":"body","ref":"CodeBlockSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBodyAndElseKeyword"},{"value":{"text":"nil"},"name":"elseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenElseKeywordAndElseBody"},{"value":{"text":"nil"},"name":"elseBody"},{"value":{"text":"nil"},"name":"unexpectedAfterElseBody"}],"type":"expr","range":{"startRow":32,"endColumn":2,"startColumn":1,"endRow":34},"id":326,"parent":325},{"token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.if)","trailingTrivia":"␣<\/span>"},"text":"if","structure":[],"id":327,"type":"other","range":{"startRow":32,"endRow":32,"startColumn":1,"endColumn":3},"parent":326},{"id":328,"parent":326,"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"2"}}],"type":"collection","range":{"startRow":32,"endRow":32,"startColumn":4,"endColumn":50},"text":"ConditionElementList"},{"id":329,"parent":328,"structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"name":"condition","value":{"text":"OptionalBindingConditionSyntax"},"ref":"OptionalBindingConditionSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","range":{"startRow":32,"startColumn":4,"endRow":32,"endColumn":28},"text":"ConditionElement"},{"id":330,"parent":329,"range":{"endRow":32,"startRow":32,"endColumn":27,"startColumn":4},"structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedAfterInitializer","value":{"text":"nil"}}],"type":"other","text":"OptionalBindingCondition"},{"token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"text":"let","structure":[],"id":331,"range":{"startColumn":4,"endRow":32,"startRow":32,"endColumn":7},"type":"other","parent":330},{"id":332,"parent":330,"range":{"startColumn":8,"endRow":32,"startRow":32,"endColumn":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("name")","text":"name"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern"},{"token":{"kind":"identifier("name")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":"name","structure":[],"range":{"startColumn":8,"startRow":32,"endRow":32,"endColumn":12},"id":333,"type":"other","parent":332},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"value","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"text":"InitializerClause","parent":330,"range":{"startColumn":13,"startRow":32,"endRow":32,"endColumn":27},"id":334,"type":"other"},{"token":{"leadingTrivia":"","kind":"equal","trailingTrivia":"␣<\/span>"},"text":"=","structure":[],"range":{"startRow":32,"endRow":32,"startColumn":13,"endColumn":14},"id":335,"type":"other","parent":334},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"possibleName","kind":"identifier("possibleName")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","parent":334,"range":{"startRow":32,"endRow":32,"startColumn":15,"endColumn":27},"id":336,"type":"expr"},{"token":{"kind":"identifier("possibleName")","leadingTrivia":"","trailingTrivia":""},"text":"possibleName","structure":[],"range":{"endRow":32,"endColumn":27,"startColumn":15,"startRow":32},"id":337,"type":"other","parent":336},{"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":",","structure":[],"range":{"endRow":32,"endColumn":28,"startColumn":27,"startRow":32},"id":338,"type":"other","parent":329},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"name":"condition","value":{"text":"OptionalBindingConditionSyntax"},"ref":"OptionalBindingConditionSyntax"},{"name":"unexpectedBetweenConditionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"ConditionElement","id":339,"parent":328,"range":{"startRow":32,"startColumn":29,"endRow":32,"endColumn":50},"type":"other"},{"parent":339,"range":{"startRow":32,"endColumn":50,"startColumn":29,"endRow":32},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndPattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedAfterInitializer"}],"id":340,"type":"other","text":"OptionalBindingCondition"},{"token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"text":"let","structure":[],"range":{"startRow":32,"endRow":32,"endColumn":32,"startColumn":29},"id":341,"type":"other","parent":340},{"parent":340,"range":{"startRow":32,"endRow":32,"endColumn":36,"startColumn":33},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"age","kind":"identifier("age")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":342,"type":"pattern","text":"IdentifierPattern"},{"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("age")","leadingTrivia":""},"text":"age","structure":[],"range":{"startRow":32,"endColumn":36,"startColumn":33,"endRow":32},"id":343,"type":"other","parent":342},{"text":"InitializerClause","range":{"startRow":32,"endColumn":50,"startColumn":37,"endRow":32},"parent":340,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"value","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"id":344,"type":"other"},{"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"text":"=","structure":[],"range":{"endRow":32,"endColumn":38,"startColumn":37,"startRow":32},"id":345,"type":"other","parent":344},{"text":"DeclReferenceExpr","range":{"endRow":32,"endColumn":50,"startColumn":39,"startRow":32},"parent":344,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"possibleAge","kind":"identifier("possibleAge")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":346,"type":"expr"},{"token":{"kind":"identifier("possibleAge")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":"possibleAge","structure":[],"range":{"startRow":32,"endRow":32,"endColumn":50,"startColumn":39},"id":347,"type":"other","parent":346},{"parent":326,"range":{"startRow":32,"startColumn":51,"endRow":34,"endColumn":2},"text":"CodeBlock","type":"other","structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":348},{"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"text":"{","structure":[],"id":349,"range":{"endRow":32,"startRow":32,"startColumn":51,"endColumn":52},"type":"other","parent":348},{"id":350,"range":{"endRow":33,"startRow":33,"startColumn":5,"endColumn":41},"parent":348,"text":"CodeBlockItemList","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection"},{"id":351,"range":{"endColumn":41,"startRow":33,"startColumn":5,"endRow":33},"parent":350,"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other"},{"id":352,"range":{"startRow":33,"endRow":33,"endColumn":41,"startColumn":5},"parent":351,"text":"FunctionCallExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr"},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","parent":352,"range":{"endRow":33,"endColumn":10,"startRow":33,"startColumn":5},"type":"expr","id":353},{"token":{"kind":"identifier("print")","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"text":"print","structure":[],"range":{"endColumn":10,"endRow":33,"startColumn":5,"startRow":33},"type":"other","id":354,"parent":353},{"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"text":"(","structure":[],"range":{"endColumn":11,"endRow":33,"startColumn":10,"startRow":33},"type":"other","id":355,"parent":352},{"range":{"endColumn":40,"endRow":33,"startColumn":11,"startRow":33},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","parent":352,"id":356,"text":"LabeledExprList"},{"range":{"startColumn":11,"endRow":33,"endColumn":40,"startRow":33},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","parent":356,"id":357,"text":"LabeledExpr"},{"range":{"startColumn":11,"endRow":33,"startRow":33,"endColumn":40},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"type":"expr","parent":357,"id":358,"text":"StringLiteralExpr"},{"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"text":""","structure":[],"range":{"startColumn":11,"endColumn":12,"startRow":33,"endRow":33},"id":359,"type":"other","parent":358},{"text":"StringLiteralSegmentList","range":{"startColumn":12,"endColumn":39,"startRow":33,"endRow":33},"id":360,"parent":358,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"5"}}],"type":"collection"},{"text":"StringSegment","range":{"startRow":33,"endRow":33,"endColumn":12,"startColumn":12},"id":361,"parent":360,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("")","text":""},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other"},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("")"},"text":"","structure":[],"range":{"startColumn":12,"startRow":33,"endColumn":12,"endRow":33},"id":362,"type":"other","parent":361},{"id":363,"parent":360,"type":"other","range":{"startColumn":12,"startRow":33,"endRow":33,"endColumn":19},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"text":"ExpressionSegment"},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"text":"\\","structure":[],"id":364,"type":"other","range":{"endRow":33,"endColumn":13,"startRow":33,"startColumn":12},"parent":363},{"id":365,"text":"(","range":{"endRow":33,"endColumn":14,"startRow":33,"startColumn":13},"parent":363,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"structure":[]},{"id":366,"parent":363,"type":"collection","range":{"endRow":33,"endColumn":18,"startRow":33,"startColumn":14},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"text":"LabeledExprList"},{"id":367,"parent":366,"type":"other","range":{"endRow":33,"endColumn":18,"startRow":33,"startColumn":14},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"LabeledExpr"},{"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":368,"parent":367,"range":{"startRow":33,"startColumn":14,"endRow":33,"endColumn":18},"type":"expr"},{"text":"name","id":369,"range":{"startColumn":14,"endRow":33,"endColumn":18,"startRow":33},"parent":368,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("name")"},"structure":[]},{"text":")","id":370,"range":{"startColumn":18,"endRow":33,"endColumn":19,"startRow":33},"parent":363,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"structure":[]},{"text":"StringSegment","parent":360,"id":371,"range":{"endColumn":23,"endRow":33,"startRow":33,"startColumn":19},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":" is ","kind":"stringSegment(" is ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other"},{"text":"␣<\/span>is␣<\/span>","id":372,"range":{"startColumn":19,"endRow":33,"endColumn":23,"startRow":33},"parent":371,"type":"other","token":{"leadingTrivia":"","kind":"stringSegment(" is ")","trailingTrivia":""},"structure":[]},{"text":"ExpressionSegment","parent":360,"id":373,"range":{"startColumn":23,"endRow":33,"endColumn":29,"startRow":33},"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"type":"other"},{"text":"\\","id":374,"range":{"endRow":33,"startColumn":23,"startRow":33,"endColumn":24},"parent":373,"type":"other","token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"structure":[]},{"id":375,"text":"(","range":{"startRow":33,"startColumn":24,"endRow":33,"endColumn":25},"parent":373,"type":"other","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"id":376,"type":"collection","text":"LabeledExprList","range":{"startRow":33,"startColumn":25,"endRow":33,"endColumn":28},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":373},{"id":377,"type":"other","text":"LabeledExpr","range":{"startRow":33,"endRow":33,"endColumn":28,"startColumn":25},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":376},{"id":378,"type":"expr","text":"DeclReferenceExpr","range":{"endColumn":28,"endRow":33,"startColumn":25,"startRow":33},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("age")","text":"age"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":377},{"text":"age","id":379,"range":{"startColumn":25,"endRow":33,"endColumn":28,"startRow":33},"parent":378,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("age")"},"structure":[]},{"text":")","id":380,"range":{"startColumn":28,"endRow":33,"endColumn":29,"startRow":33},"parent":373,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"structure":[]},{"text":"StringSegment","id":381,"range":{"startColumn":29,"endRow":33,"endColumn":39,"startRow":33},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":" years old","kind":"stringSegment(" years old")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","parent":360},{"text":"␣<\/span>years␣<\/span>old","id":382,"range":{"startColumn":29,"endRow":33,"endColumn":39,"startRow":33},"parent":381,"type":"other","token":{"kind":"stringSegment(" years old")","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"text":""","id":383,"range":{"startColumn":39,"endRow":33,"endColumn":40,"startRow":33},"parent":358,"type":"other","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"text":")","id":384,"range":{"startColumn":40,"endRow":33,"endColumn":41,"startRow":33},"parent":352,"type":"other","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"text":"MultipleTrailingClosureElementList","id":385,"range":{"startColumn":41,"endRow":33,"endColumn":41,"startRow":33},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","parent":352},{"text":"}","id":386,"range":{"startRow":34,"endRow":34,"endColumn":2,"startColumn":1},"parent":348,"type":"other","token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":""},"structure":[]},{"text":"CodeBlockItem","id":387,"range":{"startRow":37,"endRow":49,"endColumn":2,"startColumn":1},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionDeclSyntax"},"name":"item","ref":"FunctionDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","parent":1},{"range":{"startRow":37,"endRow":49,"endColumn":2,"startColumn":1},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.func)","text":"func"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"greet","kind":"identifier("greet")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"name":"signature","ref":"FunctionSignatureSyntax","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":388,"type":"decl","parent":387,"text":"FunctionDecl"},{"type":"collection","parent":388,"id":389,"text":"AttributeList","range":{"startColumn":2,"endRow":34,"startRow":34,"endColumn":2},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"type":"collection","parent":388,"id":390,"text":"DeclModifierList","range":{"endRow":34,"endColumn":2,"startColumn":2,"startRow":34},"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"id":391,"text":"func","range":{"endRow":37,"startRow":37,"startColumn":1,"endColumn":5},"parent":388,"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.func)","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Guard␣<\/span>Statements<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"structure":[]},{"id":392,"text":"greet","range":{"endRow":37,"startRow":37,"startColumn":6,"endColumn":11},"parent":388,"type":"other","token":{"kind":"identifier("greet")","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"type":"other","parent":388,"id":393,"text":"FunctionSignature","range":{"endRow":37,"startRow":37,"startColumn":11,"endColumn":37},"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"name":"parameterClause","ref":"FunctionParameterClauseSyntax","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}]},{"type":"other","id":394,"parent":393,"text":"FunctionParameterClause","range":{"endRow":37,"startColumn":11,"endColumn":37,"startRow":37},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndParameters"},{"value":{"text":"FunctionParameterListSyntax"},"ref":"FunctionParameterListSyntax","name":"parameters"},{"value":{"text":"nil"},"name":"unexpectedBetweenParametersAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}]},{"id":395,"text":"(","range":{"startColumn":11,"startRow":37,"endRow":37,"endColumn":12},"parent":394,"type":"other","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"type":"collection","id":396,"parent":394,"text":"FunctionParameterList","range":{"startColumn":12,"startRow":37,"endRow":37,"endColumn":36},"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","id":397,"parent":396,"text":"FunctionParameter","range":{"startRow":37,"endRow":37,"startColumn":12,"endColumn":36},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFirstName","value":{"text":"nil"}},{"value":{"kind":"identifier("person")","text":"person"},"name":"firstName"},{"value":{"text":"nil"},"name":"unexpectedBetweenFirstNameAndSecondName"},{"value":{"text":"nil"},"name":"secondName"},{"value":{"text":"nil"},"name":"unexpectedBetweenSecondNameAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"DictionaryTypeSyntax"},"ref":"DictionaryTypeSyntax","name":"type"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndEllipsis"},{"value":{"text":"nil"},"name":"ellipsis"},{"value":{"text":"nil"},"name":"unexpectedBetweenEllipsisAndDefaultValue"},{"value":{"text":"nil"},"name":"defaultValue"},{"value":{"text":"nil"},"name":"unexpectedBetweenDefaultValueAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"startRow":37,"startColumn":12,"endRow":37,"endColumn":12},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","id":398,"parent":397,"text":"AttributeList"},{"range":{"startColumn":12,"endRow":37,"endColumn":12,"startRow":37},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","id":399,"parent":397,"text":"DeclModifierList"},{"id":400,"text":"person","range":{"endRow":37,"endColumn":18,"startRow":37,"startColumn":12},"parent":397,"type":"other","token":{"kind":"identifier("person")","trailingTrivia":"","leadingTrivia":""},"structure":[]},{"id":401,"text":":","range":{"endRow":37,"endColumn":19,"startRow":37,"startColumn":18},"parent":397,"type":"other","token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[]},{"range":{"endRow":37,"endColumn":36,"startRow":37,"startColumn":20},"id":402,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftSquare"},{"value":{"kind":"leftSquare","text":"["},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndKey"},{"ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"},"name":"key"},{"value":{"text":"nil"},"name":"unexpectedBetweenKeyAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndValue"},{"ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedBetweenValueAndRightSquare"},{"value":{"kind":"rightSquare","text":"]"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedAfterRightSquare"}],"parent":397,"type":"type","text":"DictionaryType"},{"id":403,"text":"[","range":{"endColumn":21,"startRow":37,"startColumn":20,"endRow":37},"parent":402,"type":"other","token":{"leadingTrivia":"","kind":"leftSquare","trailingTrivia":""},"structure":[]},{"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"String","kind":"identifier("String")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"type":"type","parent":402,"range":{"endRow":37,"startColumn":21,"endColumn":27,"startRow":37},"id":404,"text":"IdentifierType"},{"id":405,"text":"String","range":{"endRow":37,"endColumn":27,"startRow":37,"startColumn":21},"parent":404,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("String")"},"structure":[]},{"id":406,"text":":","range":{"endRow":37,"endColumn":28,"startRow":37,"startColumn":27},"parent":402,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"structure":[]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("String")","text":"String"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"type":"type","parent":402,"range":{"endRow":37,"endColumn":35,"startRow":37,"startColumn":29},"id":407,"text":"IdentifierType"},{"id":408,"text":"String","range":{"startRow":37,"startColumn":29,"endColumn":35,"endRow":37},"parent":407,"type":"other","token":{"kind":"identifier("String")","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"range":{"startRow":37,"startColumn":35,"endColumn":36,"endRow":37},"structure":[],"text":"]","token":{"kind":"rightSquare","leadingTrivia":"","trailingTrivia":""},"type":"other","parent":402,"id":409},{"range":{"startRow":37,"startColumn":36,"endColumn":37,"endRow":37},"structure":[],"text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other","parent":394,"id":410},{"id":411,"parent":388,"text":"CodeBlock","range":{"startRow":37,"endColumn":2,"startColumn":38,"endRow":49},"type":"other","structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}]},{"range":{"startColumn":38,"endRow":37,"endColumn":39,"startRow":37},"structure":[],"text":"{","token":{"leadingTrivia":"","kind":"leftBrace","trailingTrivia":""},"type":"other","parent":411,"id":412},{"range":{"startColumn":5,"endRow":48,"endColumn":56,"startRow":38},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"3"}}],"id":413,"type":"collection","text":"CodeBlockItemList","parent":411},{"range":{"endColumn":6,"startColumn":5,"endRow":41,"startRow":38},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"GuardStmtSyntax"},"ref":"GuardStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":414,"type":"other","text":"CodeBlockItem","parent":413},{"range":{"endColumn":6,"startRow":38,"startColumn":5,"endRow":41},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeGuardKeyword"},{"name":"guardKeyword","value":{"text":"guard","kind":"keyword(SwiftSyntax.Keyword.guard)"}},{"name":"unexpectedBetweenGuardKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax"},{"name":"unexpectedBetweenConditionsAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":415,"type":"other","text":"GuardStmt","parent":414},{"range":{"endColumn":10,"endRow":38,"startColumn":5,"startRow":38},"structure":[],"text":"guard","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.guard)"},"parent":415,"type":"other","id":416},{"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":415,"type":"collection","text":"ConditionElementList","id":417,"range":{"endColumn":36,"endRow":38,"startColumn":11,"startRow":38}},{"structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"name":"condition","ref":"OptionalBindingConditionSyntax","value":{"text":"OptionalBindingConditionSyntax"}},{"name":"unexpectedBetweenConditionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":417,"type":"other","text":"ConditionElement","id":418,"range":{"startRow":38,"startColumn":11,"endRow":38,"endColumn":36}},{"text":"OptionalBindingCondition","type":"other","parent":418,"range":{"startColumn":11,"endColumn":36,"startRow":38,"endRow":38},"structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedAfterInitializer","value":{"text":"nil"}}],"id":419},{"range":{"startColumn":11,"startRow":38,"endColumn":14,"endRow":38},"structure":[],"text":"let","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":""},"type":"other","parent":419,"id":420},{"text":"IdentifierPattern","type":"pattern","parent":419,"range":{"startColumn":15,"startRow":38,"endColumn":19,"endRow":38},"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("name")","text":"name"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":421},{"range":{"endRow":38,"startRow":38,"startColumn":15,"endColumn":19},"structure":[],"text":"name","token":{"kind":"identifier("name")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"type":"other","parent":421,"id":422},{"text":"InitializerClause","type":"other","range":{"startRow":38,"startColumn":20,"endColumn":36,"endRow":38},"id":423,"parent":419,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","ref":"SubscriptCallExprSyntax","value":{"text":"SubscriptCallExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"range":{"startRow":38,"endColumn":21,"endRow":38,"startColumn":20},"structure":[],"text":"=","token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"type":"other","parent":423,"id":424},{"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"text":"[","kind":"leftSquare"}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"text":"]","kind":"rightSquare"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","text":"SubscriptCallExpr","parent":423,"range":{"startRow":38,"endColumn":36,"endRow":38,"startColumn":22},"id":425},{"parent":425,"type":"expr","text":"DeclReferenceExpr","id":426,"range":{"startRow":38,"endRow":38,"startColumn":22,"endColumn":28},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("person")","text":"person"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"range":{"startColumn":22,"startRow":38,"endRow":38,"endColumn":28},"structure":[],"text":"person","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("person")"},"parent":426,"type":"other","id":427},{"range":{"startColumn":28,"startRow":38,"endRow":38,"endColumn":29},"structure":[],"text":"[","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftSquare"},"parent":425,"type":"other","id":428},{"parent":425,"type":"collection","text":"LabeledExprList","id":429,"range":{"startColumn":29,"startRow":38,"endRow":38,"endColumn":35},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"parent":429,"type":"other","text":"LabeledExpr","id":430,"range":{"startColumn":29,"endRow":38,"endColumn":35,"startRow":38},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"text":"StringLiteralExpr","id":431,"range":{"startRow":38,"endRow":38,"endColumn":35,"startColumn":29},"type":"expr","structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"parent":430},{"range":{"endRow":38,"endColumn":30,"startColumn":29,"startRow":38},"structure":[],"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"type":"other","parent":431,"id":432},{"type":"collection","id":433,"parent":431,"range":{"startRow":38,"startColumn":30,"endRow":38,"endColumn":34},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"StringLiteralSegmentList"},{"type":"other","id":434,"parent":433,"range":{"endColumn":34,"endRow":38,"startRow":38,"startColumn":30},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("name")","text":"name"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment"},{"range":{"startRow":38,"startColumn":30,"endRow":38,"endColumn":34},"structure":[],"text":"name","token":{"trailingTrivia":"","kind":"stringSegment("name")","leadingTrivia":""},"type":"other","parent":434,"id":435},{"range":{"startRow":38,"startColumn":34,"endRow":38,"endColumn":35},"structure":[],"text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"type":"other","parent":431,"id":436},{"range":{"startRow":38,"startColumn":35,"endRow":38,"endColumn":36},"structure":[],"text":"]","token":{"trailingTrivia":"␣<\/span>","kind":"rightSquare","leadingTrivia":""},"type":"other","parent":425,"id":437},{"type":"collection","id":438,"parent":425,"range":{"startRow":38,"startColumn":37,"endRow":38,"endColumn":37},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"MultipleTrailingClosureElementList"},{"range":{"endColumn":41,"startRow":38,"startColumn":37,"endRow":38},"structure":[],"text":"else","token":{"kind":"keyword(SwiftSyntax.Keyword.else)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other","parent":415,"id":439},{"type":"other","id":440,"parent":415,"range":{"endColumn":6,"startRow":38,"startColumn":42,"endRow":41},"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"text":"CodeBlock"},{"range":{"endRow":38,"endColumn":43,"startColumn":42,"startRow":38},"structure":[],"text":"{","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftBrace"},"parent":440,"type":"other","id":441},{"text":"CodeBlockItemList","range":{"endRow":40,"endColumn":15,"startColumn":9,"startRow":39},"parent":440,"type":"collection","structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":442},{"text":"CodeBlockItem","range":{"startColumn":9,"startRow":39,"endColumn":34,"endRow":39},"parent":442,"type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":443},{"text":"FunctionCallExpr","range":{"startColumn":9,"startRow":39,"endRow":39,"endColumn":34},"parent":443,"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":444},{"parent":444,"range":{"endRow":39,"startColumn":9,"startRow":39,"endColumn":14},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","type":"expr","id":445},{"range":{"startRow":39,"startColumn":9,"endRow":39,"endColumn":14},"structure":[],"text":"print","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")","trailingTrivia":""},"parent":445,"type":"other","id":446},{"range":{"endColumn":15,"endRow":39,"startRow":39,"startColumn":14},"structure":[],"text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"parent":444,"type":"other","id":447},{"type":"collection","text":"LabeledExprList","id":448,"parent":444,"range":{"startColumn":15,"endRow":39,"startRow":39,"endColumn":33},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","text":"LabeledExpr","id":449,"parent":448,"range":{"endRow":39,"endColumn":33,"startRow":39,"startColumn":15},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"expression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"type":"expr","text":"StringLiteralExpr","id":450,"parent":449,"range":{"startRow":39,"endRow":39,"startColumn":15,"endColumn":33},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}]},{"range":{"startRow":39,"endRow":39,"endColumn":16,"startColumn":15},"structure":[],"text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"parent":450,"type":"other","id":451},{"text":"StringLiteralSegmentList","id":452,"parent":450,"range":{"startRow":39,"endRow":39,"endColumn":32,"startColumn":16},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"text":"StringSegment","id":453,"parent":452,"range":{"startRow":39,"startColumn":16,"endRow":39,"endColumn":32},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"No name provided","kind":"stringSegment("No name provided")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other"},{"range":{"endRow":39,"startColumn":16,"startRow":39,"endColumn":32},"structure":[],"text":"No␣<\/span>name␣<\/span>provided","token":{"kind":"stringSegment("No name provided")","trailingTrivia":"","leadingTrivia":""},"parent":453,"type":"other","id":454},{"range":{"endRow":39,"startColumn":32,"startRow":39,"endColumn":33},"structure":[],"text":""","token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"parent":450,"type":"other","id":455},{"range":{"endRow":39,"startColumn":33,"endColumn":34,"startRow":39},"structure":[],"text":")","token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"type":"other","parent":444,"id":456},{"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"range":{"startColumn":34,"startRow":39,"endRow":39,"endColumn":34},"text":"MultipleTrailingClosureElementList","type":"collection","parent":444,"id":457},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"ReturnStmtSyntax"},"ref":"ReturnStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"range":{"startRow":40,"startColumn":9,"endRow":40,"endColumn":15},"text":"CodeBlockItem","type":"other","parent":442,"id":458},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeReturnKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.return)","text":"return"},"name":"returnKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenReturnKeywordAndExpression"},{"value":{"text":"nil"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"range":{"endRow":40,"endColumn":15,"startRow":40,"startColumn":9},"text":"ReturnStmt","type":"other","parent":458,"id":459},{"type":"other","id":460,"range":{"endColumn":15,"startColumn":9,"startRow":40,"endRow":40},"parent":459,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.return)"},"structure":[],"text":"return"},{"type":"other","id":461,"range":{"endColumn":6,"startColumn":5,"startRow":41,"endRow":41},"parent":440,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"rightBrace"},"structure":[],"text":"}"},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"GuardStmtSyntax","value":{"text":"GuardStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"range":{"endColumn":6,"startColumn":5,"startRow":43,"endRow":46},"text":"CodeBlockItem","type":"other","parent":413,"id":462},{"type":"other","range":{"endColumn":6,"endRow":46,"startRow":43,"startColumn":5},"parent":462,"text":"GuardStmt","id":463,"structure":[{"name":"unexpectedBeforeGuardKeyword","value":{"text":"nil"}},{"name":"guardKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.guard)","text":"guard"}},{"name":"unexpectedBetweenGuardKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","ref":"ConditionElementListSyntax","value":{"text":"ConditionElementListSyntax"}},{"name":"unexpectedBetweenConditionsAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.else)","text":"else"}},{"name":"unexpectedBetweenElseKeywordAndBody","value":{"text":"nil"}},{"name":"body","ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}]},{"id":464,"structure":[],"range":{"startRow":43,"startColumn":5,"endRow":43,"endColumn":10},"parent":463,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.guard)"},"text":"guard","type":"other"},{"type":"collection","range":{"startRow":43,"startColumn":11,"endRow":43,"endColumn":57},"parent":463,"text":"ConditionElementList","id":465,"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"2"}}]},{"range":{"endRow":43,"startRow":43,"endColumn":35,"startColumn":11},"type":"other","text":"ConditionElement","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"value":{"text":"OptionalBindingConditionSyntax"},"name":"condition","ref":"OptionalBindingConditionSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":466,"parent":465},{"range":{"endColumn":34,"startColumn":11,"endRow":43,"startRow":43},"type":"other","text":"OptionalBindingCondition","structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedAfterInitializer","value":{"text":"nil"}}],"id":467,"parent":466},{"structure":[],"id":468,"range":{"startColumn":11,"endRow":43,"startRow":43,"endColumn":14},"parent":467,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"text":"let","type":"other"},{"text":"IdentifierPattern","id":469,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("age")","text":"age"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"type":"pattern","parent":467,"range":{"startColumn":15,"endColumn":18,"endRow":43,"startRow":43}},{"id":470,"type":"other","parent":469,"range":{"endColumn":18,"startRow":43,"startColumn":15,"endRow":43},"token":{"kind":"identifier("age")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":"age","structure":[]},{"text":"InitializerClause","id":471,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"SubscriptCallExprSyntax"},"ref":"SubscriptCallExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"type":"other","parent":467,"range":{"endColumn":34,"startRow":43,"startColumn":19,"endRow":43}},{"id":472,"type":"other","parent":471,"range":{"endRow":43,"endColumn":20,"startColumn":19,"startRow":43},"token":{"kind":"equal","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":"=","structure":[]},{"text":"SubscriptCallExpr","id":473,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"kind":"leftSquare","text":"["}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","parent":471,"range":{"endRow":43,"endColumn":34,"startColumn":21,"startRow":43}},{"parent":473,"range":{"startColumn":21,"endRow":43,"endColumn":27,"startRow":43},"id":474,"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("person")","text":"person"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"id":475,"type":"other","parent":474,"range":{"startRow":43,"endRow":43,"endColumn":27,"startColumn":21},"token":{"trailingTrivia":"","kind":"identifier("person")","leadingTrivia":""},"text":"person","structure":[]},{"id":476,"type":"other","parent":473,"range":{"startRow":43,"endRow":43,"endColumn":28,"startColumn":27},"token":{"trailingTrivia":"","kind":"leftSquare","leadingTrivia":""},"text":"[","structure":[]},{"parent":473,"range":{"startRow":43,"endRow":43,"endColumn":33,"startColumn":28},"id":477,"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection"},{"parent":477,"text":"LabeledExpr","range":{"endRow":43,"startRow":43,"endColumn":33,"startColumn":28},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":478},{"parent":478,"text":"StringLiteralExpr","range":{"endColumn":33,"startRow":43,"endRow":43,"startColumn":28},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"type":"expr","id":479},{"id":480,"text":""","parent":479,"range":{"endColumn":29,"startColumn":28,"endRow":43,"startRow":43},"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"structure":[],"type":"other"},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":479,"type":"collection","range":{"endColumn":32,"startColumn":29,"endRow":43,"startRow":43},"id":481,"text":"StringLiteralSegmentList"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"age","kind":"stringSegment("age")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"parent":481,"type":"other","range":{"startRow":43,"startColumn":29,"endRow":43,"endColumn":32},"id":482,"text":"StringSegment"},{"id":483,"text":"age","parent":482,"range":{"startRow":43,"endRow":43,"startColumn":29,"endColumn":32},"token":{"kind":"stringSegment("age")","leadingTrivia":"","trailingTrivia":""},"structure":[],"type":"other"},{"id":484,"text":""","parent":479,"range":{"startRow":43,"endRow":43,"startColumn":32,"endColumn":33},"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"type":"other"},{"id":485,"text":"]","parent":473,"range":{"startRow":43,"endRow":43,"startColumn":33,"endColumn":34},"token":{"kind":"rightSquare","leadingTrivia":"","trailingTrivia":""},"structure":[],"type":"other"},{"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":473,"type":"collection","range":{"startRow":43,"endRow":43,"startColumn":34,"endColumn":34},"id":486,"text":"MultipleTrailingClosureElementList"},{"id":487,"text":",","parent":466,"range":{"startRow":43,"endRow":43,"startColumn":34,"endColumn":35},"token":{"trailingTrivia":"␣<\/span>","kind":"comma","leadingTrivia":""},"structure":[],"type":"other"},{"parent":465,"id":488,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"value":{"text":"OptionalBindingConditionSyntax"},"name":"condition","ref":"OptionalBindingConditionSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ConditionElement","range":{"startRow":43,"endRow":43,"startColumn":36,"endColumn":57}},{"parent":488,"id":489,"structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedAfterInitializer","value":{"text":"nil"}}],"type":"other","text":"OptionalBindingCondition","range":{"startColumn":36,"startRow":43,"endColumn":57,"endRow":43}},{"id":490,"text":"let","parent":489,"range":{"endColumn":39,"startColumn":36,"endRow":43,"startRow":43},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"structure":[],"type":"other"},{"text":"IdentifierPattern","parent":489,"id":491,"range":{"endColumn":46,"startColumn":40,"endRow":43,"startRow":43},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("ageInt")","text":"ageInt"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern"},{"id":492,"type":"other","parent":491,"range":{"endRow":43,"startColumn":40,"startRow":43,"endColumn":46},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("ageInt")"},"text":"ageInt","structure":[]},{"text":"InitializerClause","parent":489,"id":493,"range":{"endRow":43,"startColumn":47,"startRow":43,"endColumn":57},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"FunctionCallExprSyntax"},"name":"value","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"type":"other"},{"id":494,"type":"other","parent":493,"range":{"startColumn":47,"endRow":43,"endColumn":48,"startRow":43},"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"text":"=","structure":[]},{"text":"FunctionCallExpr","parent":493,"id":495,"range":{"startColumn":49,"endRow":43,"endColumn":57,"startRow":43},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr"},{"id":496,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("Int")","text":"Int"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"text":"DeclReferenceExpr","range":{"endColumn":52,"startRow":43,"startColumn":49,"endRow":43},"parent":495,"type":"expr"},{"id":497,"type":"other","range":{"startRow":43,"endRow":43,"endColumn":52,"startColumn":49},"parent":496,"token":{"kind":"identifier("Int")","trailingTrivia":"","leadingTrivia":""},"structure":[],"text":"Int"},{"id":498,"type":"other","range":{"startRow":43,"endRow":43,"endColumn":53,"startColumn":52},"parent":495,"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"structure":[],"text":"("},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":495,"text":"LabeledExprList","id":499,"range":{"startColumn":53,"endColumn":56,"endRow":43,"startRow":43}},{"id":500,"parent":499,"range":{"startRow":43,"endRow":43,"startColumn":53,"endColumn":56},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr"},{"id":501,"parent":500,"range":{"startRow":43,"endColumn":56,"startColumn":53,"endRow":43},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"age","kind":"identifier("age")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","text":"DeclReferenceExpr"},{"id":502,"text":"age","parent":501,"range":{"endRow":43,"startRow":43,"startColumn":53,"endColumn":56},"token":{"leadingTrivia":"","kind":"identifier("age")","trailingTrivia":""},"structure":[],"type":"other"},{"type":"other","id":503,"range":{"endRow":43,"startRow":43,"endColumn":57,"startColumn":56},"parent":495,"token":{"kind":"rightParen","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":")","structure":[]},{"text":"MultipleTrailingClosureElementList","range":{"endRow":43,"startRow":43,"endColumn":58,"startColumn":58},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":495,"type":"collection","id":504},{"type":"other","id":505,"range":{"startColumn":58,"startRow":43,"endRow":43,"endColumn":62},"parent":463,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.else)"},"text":"else","structure":[]},{"text":"CodeBlock","range":{"startColumn":63,"startRow":43,"endRow":46,"endColumn":6},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":463,"type":"other","id":506},{"range":{"endRow":43,"startColumn":63,"startRow":43,"endColumn":64},"text":"{","structure":[],"parent":506,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"id":507},{"text":"CodeBlockItemList","range":{"endRow":45,"startColumn":9,"startRow":44,"endColumn":15},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"parent":506,"type":"collection","id":508},{"text":"CodeBlockItem","range":{"endColumn":38,"endRow":44,"startColumn":9,"startRow":44},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":508,"type":"other","id":509},{"range":{"startColumn":9,"endRow":44,"startRow":44,"endColumn":38},"id":510,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"text":"FunctionCallExpr","type":"expr","parent":509},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":511,"parent":510,"text":"DeclReferenceExpr","type":"expr","range":{"startRow":44,"endRow":44,"startColumn":9,"endColumn":14}},{"structure":[],"text":"print","parent":511,"type":"other","range":{"endColumn":14,"endRow":44,"startColumn":9,"startRow":44},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"id":512},{"structure":[],"text":"(","parent":510,"type":"other","range":{"endColumn":15,"endRow":44,"startColumn":14,"startRow":44},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"id":513},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":514,"parent":510,"text":"LabeledExprList","type":"collection","range":{"endColumn":37,"endRow":44,"startColumn":15,"startRow":44}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":515,"parent":514,"text":"LabeledExpr","type":"other","range":{"endColumn":37,"startColumn":15,"endRow":44,"startRow":44}},{"id":516,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"range":{"endRow":44,"startRow":44,"startColumn":15,"endColumn":37},"text":"StringLiteralExpr","type":"expr","parent":515},{"structure":[],"range":{"endColumn":16,"startRow":44,"startColumn":15,"endRow":44},"text":""","type":"other","parent":516,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"id":517},{"range":{"startRow":44,"startColumn":16,"endColumn":36,"endRow":44},"id":518,"parent":516,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"StringLiteralSegmentList","type":"collection"},{"range":{"startColumn":16,"startRow":44,"endRow":44,"endColumn":36},"id":519,"parent":518,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("Invalid age provided")","text":"Invalid age provided"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment","type":"other"},{"range":{"startRow":44,"endColumn":36,"startColumn":16,"endRow":44},"structure":[],"parent":519,"text":"Invalid␣<\/span>age␣<\/span>provided","type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Invalid age provided")"},"id":520},{"range":{"startRow":44,"endColumn":37,"startColumn":36,"endRow":44},"structure":[],"parent":516,"text":""","type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"id":521},{"range":{"startRow":44,"endColumn":38,"startColumn":37,"endRow":44},"structure":[],"parent":510,"text":")","type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"id":522},{"range":{"startRow":44,"endColumn":38,"startColumn":38,"endRow":44},"id":523,"parent":510,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"MultipleTrailingClosureElementList","type":"collection"},{"range":{"endColumn":15,"startColumn":9,"startRow":45,"endRow":45},"id":524,"parent":508,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"ReturnStmtSyntax","name":"item","value":{"text":"ReturnStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","type":"other"},{"text":"ReturnStmt","range":{"endRow":45,"startColumn":9,"endColumn":15,"startRow":45},"structure":[{"name":"unexpectedBeforeReturnKeyword","value":{"text":"nil"}},{"name":"returnKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.return)","text":"return"}},{"name":"unexpectedBetweenReturnKeywordAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"nil"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"other","parent":524,"id":525},{"range":{"endRow":45,"startRow":45,"startColumn":9,"endColumn":15},"text":"return","structure":[],"type":"other","parent":525,"token":{"kind":"keyword(SwiftSyntax.Keyword.return)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"id":526},{"range":{"endRow":46,"startRow":46,"startColumn":5,"endColumn":6},"text":"}","structure":[],"type":"other","parent":506,"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"id":527},{"text":"CodeBlockItem","range":{"endRow":48,"startRow":48,"startColumn":5,"endColumn":56},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","parent":413,"id":528},{"text":"FunctionCallExpr","range":{"endRow":48,"startRow":48,"startColumn":5,"endColumn":56},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","parent":528,"id":529},{"id":530,"parent":529,"range":{"startRow":48,"startColumn":5,"endRow":48,"endColumn":10},"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"range":{"startColumn":5,"endColumn":10,"endRow":48,"startRow":48},"text":"print","parent":530,"structure":[],"type":"other","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"id":531},{"range":{"startRow":48,"startColumn":10,"endRow":48,"endColumn":11},"type":"other","parent":529,"text":"(","structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"id":532},{"type":"collection","id":533,"range":{"startRow":48,"startColumn":11,"endRow":48,"endColumn":55},"parent":529,"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"type":"other","id":534,"range":{"startRow":48,"startColumn":11,"endRow":48,"endColumn":55},"parent":533,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"type":"expr","id":535,"range":{"startRow":48,"startColumn":11,"endRow":48,"endColumn":55},"parent":534,"text":"StringLiteralExpr","structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}]},{"range":{"startColumn":11,"endRow":48,"startRow":48,"endColumn":12},"type":"other","parent":535,"structure":[],"text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"id":536},{"id":537,"type":"collection","parent":535,"range":{"startColumn":12,"endRow":48,"startRow":48,"endColumn":54},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"5"}}],"text":"StringLiteralSegmentList"},{"id":538,"type":"other","parent":537,"range":{"startRow":48,"startColumn":12,"endRow":48,"endColumn":18},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Hello ")","text":"Hello "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"text":"StringSegment"},{"range":{"endColumn":18,"endRow":48,"startColumn":12,"startRow":48},"type":"other","parent":538,"structure":[],"text":"Hello␣<\/span>","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Hello ")"},"id":539},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":537,"range":{"endRow":48,"startRow":48,"startColumn":18,"endColumn":25},"type":"other","id":540,"text":"ExpressionSegment"},{"range":{"endColumn":19,"startColumn":18,"endRow":48,"startRow":48},"type":"other","parent":540,"structure":[],"text":"\\","token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"id":541},{"range":{"endColumn":20,"startColumn":19,"endRow":48,"startRow":48},"type":"other","parent":540,"structure":[],"text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"id":542},{"type":"collection","parent":540,"range":{"endColumn":24,"startColumn":20,"endRow":48,"startRow":48},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":543,"text":"LabeledExprList"},{"type":"other","parent":543,"range":{"endRow":48,"startRow":48,"endColumn":24,"startColumn":20},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":544,"text":"LabeledExpr"},{"type":"expr","id":545,"parent":544,"text":"DeclReferenceExpr","range":{"endColumn":24,"startColumn":20,"startRow":48,"endRow":48},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("name")","text":"name"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"range":{"endRow":48,"startRow":48,"startColumn":20,"endColumn":24},"type":"other","parent":545,"text":"name","structure":[],"token":{"kind":"identifier("name")","trailingTrivia":"","leadingTrivia":""},"id":546},{"range":{"endRow":48,"startRow":48,"startColumn":24,"endColumn":25},"type":"other","parent":540,"text":")","structure":[],"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"id":547},{"type":"other","id":548,"parent":537,"text":"StringSegment","range":{"endRow":48,"startRow":48,"startColumn":25,"endColumn":35},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(", you are ")","text":", you are "},"name":"content"},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"structure":[],"text":",␣<\/span>you␣<\/span>are␣<\/span>","parent":548,"range":{"endRow":48,"endColumn":35,"startRow":48,"startColumn":25},"type":"other","token":{"kind":"stringSegment(", you are ")","trailingTrivia":"","leadingTrivia":""},"id":549},{"id":550,"parent":537,"text":"ExpressionSegment","structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"range":{"endRow":48,"endColumn":44,"startRow":48,"startColumn":35},"type":"other"},{"structure":[],"text":"\\","parent":550,"range":{"startColumn":35,"endRow":48,"startRow":48,"endColumn":36},"type":"other","token":{"kind":"backslash","trailingTrivia":"","leadingTrivia":""},"id":551},{"structure":[],"text":"(","parent":550,"range":{"startColumn":36,"endRow":48,"startRow":48,"endColumn":37},"type":"other","token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"id":552},{"id":553,"text":"LabeledExprList","parent":550,"range":{"endColumn":43,"endRow":48,"startColumn":37,"startRow":48},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"range":{"endColumn":43,"endRow":48,"startColumn":37,"startRow":48},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":554,"type":"other","text":"LabeledExpr","parent":553},{"range":{"endRow":48,"startRow":48,"endColumn":43,"startColumn":37},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"ageInt","kind":"identifier("ageInt")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":555,"type":"expr","text":"DeclReferenceExpr","parent":554},{"range":{"endRow":48,"startColumn":37,"endColumn":43,"startRow":48},"structure":[],"type":"other","text":"ageInt","parent":555,"token":{"leadingTrivia":"","kind":"identifier("ageInt")","trailingTrivia":""},"id":556},{"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"range":{"endRow":48,"startColumn":43,"endColumn":44,"startRow":48},"type":"other","text":")","parent":550,"id":557},{"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(" years old")","text":" years old"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment","parent":537,"type":"other","range":{"endRow":48,"startColumn":44,"endColumn":54,"startRow":48},"id":558},{"structure":[],"token":{"kind":"stringSegment(" years old")","trailingTrivia":"","leadingTrivia":""},"range":{"endColumn":54,"startColumn":44,"endRow":48,"startRow":48},"type":"other","text":"␣<\/span>years␣<\/span>old","parent":558,"id":559},{"structure":[],"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"range":{"endColumn":55,"startColumn":54,"endRow":48,"startRow":48},"type":"other","text":""","parent":535,"id":560},{"structure":[],"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"range":{"endColumn":56,"startColumn":55,"endRow":48,"startRow":48},"type":"other","text":")","parent":529,"id":561},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"text":"MultipleTrailingClosureElementList","parent":529,"type":"collection","range":{"endColumn":56,"startColumn":56,"endRow":48,"startRow":48},"id":562},{"structure":[],"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"endRow":49,"endColumn":2,"startColumn":1,"startRow":49},"type":"other","text":"}","parent":411,"id":563},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","parent":1,"type":"other","range":{"endRow":53,"endColumn":26,"startColumn":1,"startRow":53},"id":564},{"text":"VariableDecl","id":565,"range":{"endColumn":26,"endRow":53,"startRow":53,"startColumn":1},"type":"decl","parent":564,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"ref":"PatternBindingListSyntax","name":"bindings","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}]},{"text":"AttributeList","id":566,"range":{"endRow":49,"startRow":49,"startColumn":2,"endColumn":2},"type":"collection","parent":565,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"text":"DeclModifierList","id":567,"range":{"startRow":49,"endRow":49,"endColumn":2,"startColumn":2},"type":"collection","parent":565,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"structure":[],"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Switch␣<\/span>Statements<\/span>↲<\/span>\/\/␣<\/span>Switch␣<\/span>with␣<\/span>range␣<\/span>matching<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"range":{"endRow":53,"startColumn":1,"endColumn":4,"startRow":53},"type":"other","text":"let","parent":565,"id":568},{"type":"collection","parent":565,"id":569,"text":"PatternBindingList","structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"range":{"endColumn":26,"startRow":53,"startColumn":5,"endRow":53}},{"type":"other","parent":569,"id":570,"text":"PatternBinding","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"startColumn":5,"startRow":53,"endRow":53,"endColumn":26}},{"type":"pattern","parent":570,"id":571,"text":"IdentifierPattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"approximateCount","kind":"identifier("approximateCount")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"range":{"startRow":53,"endColumn":21,"startColumn":5,"endRow":53}},{"structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("approximateCount")","leadingTrivia":""},"range":{"startRow":53,"startColumn":5,"endRow":53,"endColumn":21},"type":"other","text":"approximateCount","parent":571,"id":572},{"parent":570,"range":{"startRow":53,"startColumn":22,"endRow":53,"endColumn":26},"type":"other","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"value","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":573,"text":"InitializerClause"},{"structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"range":{"startRow":53,"endColumn":23,"endRow":53,"startColumn":22},"type":"other","text":"=","parent":573,"id":574},{"parent":573,"range":{"startRow":53,"endColumn":26,"endRow":53,"startColumn":24},"type":"expr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"62","kind":"integerLiteral("62")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":575,"text":"IntegerLiteralExpr"},{"structure":[],"token":{"kind":"integerLiteral("62")","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":24,"endColumn":26,"endRow":53,"startRow":53},"type":"other","text":"62","parent":575,"id":576},{"parent":1,"range":{"startColumn":1,"endColumn":44,"endRow":54,"startRow":54},"type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":577,"text":"CodeBlockItem"},{"type":"decl","range":{"startRow":54,"startColumn":1,"endRow":54,"endColumn":44},"text":"VariableDecl","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax","name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"id":578,"parent":577},{"type":"collection","range":{"startRow":53,"startColumn":26,"endRow":53,"endColumn":26},"text":"AttributeList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":579,"parent":578},{"type":"collection","range":{"endColumn":26,"endRow":53,"startColumn":26,"startRow":53},"text":"DeclModifierList","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":580,"parent":578},{"structure":[],"token":{"kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"range":{"endRow":54,"startColumn":1,"startRow":54,"endColumn":4},"type":"other","text":"let","parent":578,"id":581},{"type":"collection","parent":578,"id":582,"text":"PatternBindingList","range":{"endRow":54,"startRow":54,"endColumn":44,"startColumn":5},"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","parent":582,"id":583,"text":"PatternBinding","range":{"endRow":54,"startColumn":5,"endColumn":44,"startRow":54},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"type":"pattern","parent":583,"id":584,"text":"IdentifierPattern","range":{"endColumn":18,"startRow":54,"startColumn":5,"endRow":54},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"countedThings","kind":"identifier("countedThings")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}]},{"structure":[],"token":{"kind":"identifier("countedThings")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"startColumn":5,"endRow":54,"startRow":54,"endColumn":18},"type":"other","text":"countedThings","parent":584,"id":585},{"type":"other","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"value","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":586,"text":"InitializerClause","parent":583,"range":{"startColumn":19,"endRow":54,"startRow":54,"endColumn":44}},{"structure":[],"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":54,"endRow":54,"startColumn":19,"endColumn":20},"type":"other","text":"=","parent":586,"id":587},{"type":"expr","structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"id":588,"text":"StringLiteralExpr","parent":586,"range":{"startRow":54,"endRow":54,"startColumn":21,"endColumn":44}},{"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"range":{"endColumn":22,"startColumn":21,"startRow":54,"endRow":54},"type":"other","text":""","parent":588,"id":589},{"type":"collection","parent":588,"id":590,"range":{"endColumn":43,"startColumn":22,"startRow":54,"endRow":54},"text":"StringLiteralSegmentList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","parent":590,"id":591,"range":{"startColumn":22,"endRow":54,"endColumn":43,"startRow":54},"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("moons orbiting Saturn")","text":"moons orbiting Saturn"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"structure":[],"token":{"kind":"stringSegment("moons orbiting Saturn")","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":22,"endRow":54,"startRow":54,"endColumn":43},"type":"other","text":"moons␣<\/span>orbiting␣<\/span>Saturn","parent":591,"id":592},{"structure":[],"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":43,"endRow":54,"startRow":54,"endColumn":44},"type":"other","text":""","parent":588,"id":593},{"type":"other","parent":1,"id":594,"range":{"startColumn":1,"endRow":55,"startRow":55,"endColumn":25},"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"range":{"startRow":55,"endRow":55,"endColumn":25,"startColumn":1},"type":"decl","structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"text":"VariableDecl","id":595,"parent":594},{"range":{"endRow":54,"startRow":54,"endColumn":44,"startColumn":44},"type":"collection","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"text":"AttributeList","id":596,"parent":595},{"range":{"endColumn":44,"startColumn":44,"startRow":54,"endRow":54},"type":"collection","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"DeclModifierList","id":597,"parent":595},{"structure":[],"token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"range":{"startColumn":1,"startRow":55,"endRow":55,"endColumn":4},"type":"other","text":"let","parent":595,"id":598},{"parent":595,"type":"collection","structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"startRow":55,"endRow":55,"endColumn":25,"startColumn":5},"text":"PatternBindingList","id":599},{"parent":599,"type":"other","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"ref":"TypeAnnotationSyntax","name":"typeAnnotation","value":{"text":"TypeAnnotationSyntax"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"nil"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endRow":55,"endColumn":25,"startRow":55,"startColumn":5},"text":"PatternBinding","id":600},{"parent":600,"type":"pattern","structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("naturalCount")","text":"naturalCount"}},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"range":{"startColumn":5,"endColumn":17,"endRow":55,"startRow":55},"text":"IdentifierPattern","id":601},{"structure":[],"token":{"leadingTrivia":"","kind":"identifier("naturalCount")","trailingTrivia":""},"range":{"startRow":55,"startColumn":5,"endColumn":17,"endRow":55},"type":"other","text":"naturalCount","parent":601,"id":602},{"parent":600,"text":"TypeAnnotation","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax","name":"type"},{"value":{"text":"nil"},"name":"unexpectedAfterType"}],"range":{"startRow":55,"startColumn":17,"endColumn":25,"endRow":55},"type":"other","id":603},{"structure":[],"token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"endColumn":18,"startRow":55,"startColumn":17,"endRow":55},"type":"other","text":":","parent":603,"id":604},{"parent":603,"text":"IdentifierType","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"String","kind":"identifier("String")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"range":{"endColumn":25,"startRow":55,"startColumn":19,"endRow":55},"type":"type","id":605},{"structure":[],"token":{"kind":"identifier("String")","trailingTrivia":"","leadingTrivia":""},"range":{"endRow":55,"endColumn":25,"startRow":55,"startColumn":19},"type":"other","text":"String","parent":605,"id":606},{"parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"ExpressionStmtSyntax"},"ref":"ExpressionStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","text":"CodeBlockItem","id":607,"range":{"startRow":56,"startColumn":1,"endColumn":2,"endRow":69}},{"text":"ExpressionStmt","parent":607,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"SwitchExprSyntax"},"ref":"SwitchExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"id":608,"range":{"endColumn":2,"startRow":56,"endRow":69,"startColumn":1},"type":"other"},{"text":"SwitchExpr","parent":608,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeSwitchKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.switch)","text":"switch"},"name":"switchKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenSwitchKeywordAndSubject"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"subject"},{"value":{"text":"nil"},"name":"unexpectedBetweenSubjectAndLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndCases"},{"value":{"text":"SwitchCaseListSyntax"},"ref":"SwitchCaseListSyntax","name":"cases"},{"value":{"text":"nil"},"name":"unexpectedBetweenCasesAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"id":609,"range":{"endColumn":2,"startColumn":1,"startRow":56,"endRow":69},"type":"expr"},{"structure":[],"token":{"kind":"keyword(SwiftSyntax.Keyword.switch)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"range":{"startColumn":1,"endColumn":7,"startRow":56,"endRow":56},"type":"other","text":"switch","parent":609,"id":610},{"id":611,"type":"expr","text":"DeclReferenceExpr","parent":609,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"approximateCount","kind":"identifier("approximateCount")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"range":{"startColumn":8,"endColumn":24,"startRow":56,"endRow":56}},{"structure":[],"token":{"kind":"identifier("approximateCount")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"startRow":56,"endColumn":24,"startColumn":8,"endRow":56},"type":"other","text":"approximateCount","parent":611,"id":612},{"text":"{","range":{"startRow":56,"endColumn":26,"startColumn":25,"endRow":56},"type":"other","id":613,"token":{"kind":"leftBrace","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":609},{"id":614,"type":"collection","text":"SwitchCaseList","parent":609,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"6"}}],"range":{"startRow":57,"endColumn":26,"startColumn":1,"endRow":68}},{"id":615,"type":"other","text":"SwitchCase","parent":614,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeAndLabel"},{"ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedAfterStatements"}],"range":{"endRow":58,"startRow":57,"startColumn":1,"endColumn":24}},{"text":"SwitchCaseLabel","id":616,"parent":615,"range":{"startColumn":1,"endRow":57,"startRow":57,"endColumn":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCaseKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndCaseItems"},{"value":{"text":"SwitchCaseItemListSyntax"},"ref":"SwitchCaseItemListSyntax","name":"caseItems"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"type":"other"},{"text":"case","range":{"startRow":57,"endRow":57,"endColumn":5,"startColumn":1},"type":"other","id":617,"token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)","trailingTrivia":"␣<\/span>"},"structure":[],"parent":616},{"text":"SwitchCaseItemList","id":618,"parent":616,"range":{"startRow":57,"endRow":57,"endColumn":7,"startColumn":6},"structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"text":"SwitchCaseItem","id":619,"parent":618,"range":{"startRow":57,"endRow":57,"endColumn":7,"startColumn":6},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"value":{"text":"ExpressionPatternSyntax"},"ref":"ExpressionPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"parent":619,"id":620,"range":{"endRow":57,"startColumn":6,"startRow":57,"endColumn":7},"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"text":"ExpressionPattern","type":"pattern"},{"parent":620,"id":621,"range":{"startColumn":6,"endColumn":7,"startRow":57,"endRow":57},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"0","kind":"integerLiteral("0")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"text":"IntegerLiteralExpr","type":"expr"},{"range":{"startRow":57,"startColumn":6,"endRow":57,"endColumn":7},"text":"0","type":"other","id":622,"token":{"kind":"integerLiteral("0")","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":621},{"range":{"startRow":57,"startColumn":7,"endRow":57,"endColumn":8},"text":":","type":"other","id":623,"token":{"kind":"colon","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":616},{"parent":615,"id":624,"range":{"startRow":58,"startColumn":5,"endRow":58,"endColumn":24},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"text":"CodeBlockItemList","type":"collection"},{"range":{"startColumn":5,"endColumn":24,"endRow":58,"startRow":58},"id":625,"type":"other","text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":624},{"range":{"startRow":58,"startColumn":5,"endRow":58,"endColumn":24},"id":626,"type":"expr","text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"AssignmentExprSyntax"},"ref":"AssignmentExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"parent":625},{"range":{"endColumn":17,"startColumn":5,"endRow":58,"startRow":58},"id":627,"type":"expr","text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"naturalCount","kind":"identifier("naturalCount")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":626},{"text":"naturalCount","range":{"startColumn":5,"endColumn":17,"endRow":58,"startRow":58},"type":"other","id":628,"token":{"kind":"identifier("naturalCount")","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"parent":627},{"text":"AssignmentExpr","range":{"startColumn":18,"endColumn":19,"endRow":58,"startRow":58},"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"parent":626,"type":"expr","id":629},{"text":"=","range":{"startColumn":18,"endColumn":19,"startRow":58,"endRow":58},"type":"other","id":630,"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"parent":629},{"text":"StringLiteralExpr","range":{"startColumn":20,"endColumn":24,"startRow":58,"endRow":58},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"parent":626,"type":"expr","id":631},{"text":""","range":{"startRow":58,"startColumn":20,"endRow":58,"endColumn":21},"type":"other","id":632,"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":631},{"text":"StringLiteralSegmentList","id":633,"range":{"startRow":58,"startColumn":21,"endRow":58,"endColumn":23},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":631},{"text":"StringSegment","id":634,"range":{"endRow":58,"endColumn":23,"startRow":58,"startColumn":21},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("no")","text":"no"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","parent":633},{"text":"no","range":{"startRow":58,"startColumn":21,"endRow":58,"endColumn":23},"type":"other","id":635,"token":{"kind":"stringSegment("no")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":634},{"text":""","range":{"startRow":58,"startColumn":23,"endRow":58,"endColumn":24},"type":"other","id":636,"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":631},{"text":"SwitchCase","id":637,"range":{"startRow":59,"startColumn":1,"endRow":60,"endColumn":27},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeAndLabel"},{"value":{"text":"SwitchCaseLabelSyntax"},"ref":"SwitchCaseLabelSyntax","name":"label"},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other","parent":614},{"range":{"startRow":59,"startColumn":1,"endRow":59,"endColumn":12},"text":"SwitchCaseLabel","parent":637,"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"text":"case","kind":"keyword(SwiftSyntax.Keyword.case)"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"ref":"SwitchCaseItemListSyntax","name":"caseItems","value":{"text":"SwitchCaseItemListSyntax"}},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"type":"other","id":638},{"range":{"startRow":59,"startColumn":1,"endRow":59,"endColumn":5},"text":"case","type":"other","id":639,"token":{"kind":"keyword(SwiftSyntax.Keyword.case)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"structure":[],"parent":638},{"range":{"startRow":59,"startColumn":6,"endRow":59,"endColumn":11},"text":"SwitchCaseItemList","parent":638,"structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":640},{"range":{"startColumn":6,"endRow":59,"endColumn":11,"startRow":59},"text":"SwitchCaseItem","parent":640,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"ExpressionPatternSyntax"},"ref":"ExpressionPatternSyntax"},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":641},{"type":"pattern","text":"ExpressionPattern","id":642,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"expression","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"range":{"startColumn":6,"startRow":59,"endRow":59,"endColumn":11},"parent":641},{"type":"expr","text":"InfixOperatorExpr","id":643,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"leftOperand","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"BinaryOperatorExprSyntax"},"name":"operator","ref":"BinaryOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"range":{"startColumn":6,"endRow":59,"startRow":59,"endColumn":11},"parent":642},{"type":"expr","text":"IntegerLiteralExpr","id":644,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"1","kind":"integerLiteral("1")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"range":{"startColumn":6,"endColumn":7,"startRow":59,"endRow":59},"parent":643},{"text":"1","range":{"endColumn":7,"startColumn":6,"startRow":59,"endRow":59},"type":"other","id":645,"token":{"leadingTrivia":"","kind":"integerLiteral("1")","trailingTrivia":""},"structure":[],"parent":644},{"type":"expr","parent":643,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator("..<")","text":"..<"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"id":646,"text":"BinaryOperatorExpr","range":{"endColumn":10,"startColumn":7,"startRow":59,"endRow":59}},{"text":"..<","range":{"startRow":59,"endColumn":10,"startColumn":7,"endRow":59},"type":"other","id":647,"token":{"kind":"binaryOperator("..<")","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":646},{"type":"expr","parent":643,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("5")","text":"5"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":648,"text":"IntegerLiteralExpr","range":{"startRow":59,"endColumn":11,"startColumn":10,"endRow":59}},{"text":"5","range":{"startRow":59,"endRow":59,"startColumn":10,"endColumn":11},"type":"other","id":649,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("5")"},"structure":[],"parent":648},{"text":":","range":{"startRow":59,"endRow":59,"startColumn":11,"endColumn":12},"type":"other","id":650,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"colon"},"structure":[],"parent":638},{"type":"collection","parent":637,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":651,"text":"CodeBlockItemList","range":{"startRow":60,"endRow":60,"startColumn":5,"endColumn":27}},{"range":{"endColumn":27,"startRow":60,"startColumn":5,"endRow":60},"parent":651,"id":652,"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other"},{"range":{"startColumn":5,"endColumn":27,"endRow":60,"startRow":60},"parent":652,"id":653,"text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"rightOperand","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr"},{"range":{"startRow":60,"endRow":60,"endColumn":17,"startColumn":5},"parent":653,"id":654,"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("naturalCount")","text":"naturalCount"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"range":{"startRow":60,"endColumn":17,"endRow":60,"startColumn":5},"text":"naturalCount","type":"other","id":655,"token":{"kind":"identifier("naturalCount")","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"parent":654},{"range":{"startRow":60,"endColumn":19,"endRow":60,"startColumn":18},"text":"AssignmentExpr","parent":653,"id":656,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"type":"expr"},{"range":{"startColumn":18,"endColumn":19,"startRow":60,"endRow":60},"text":"=","type":"other","id":657,"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"parent":656},{"range":{"startColumn":20,"endColumn":27,"startRow":60,"endRow":60},"text":"StringLiteralExpr","parent":653,"id":658,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr"},{"range":{"endRow":60,"endColumn":21,"startRow":60,"startColumn":20},"text":""","type":"other","id":659,"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":658},{"id":660,"range":{"endRow":60,"endColumn":26,"startRow":60,"startColumn":21},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"StringLiteralSegmentList","type":"collection","parent":658},{"id":661,"range":{"endColumn":26,"startRow":60,"endRow":60,"startColumn":21},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"a few","kind":"stringSegment("a few")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"text":"StringSegment","type":"other","parent":660},{"range":{"endRow":60,"startColumn":21,"endColumn":26,"startRow":60},"text":"a␣<\/span>few","type":"other","id":662,"token":{"leadingTrivia":"","kind":"stringSegment("a few")","trailingTrivia":""},"structure":[],"parent":661},{"range":{"endRow":60,"startColumn":26,"endColumn":27,"startRow":60},"text":""","type":"other","id":663,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"structure":[],"parent":658},{"id":664,"range":{"endRow":62,"startColumn":1,"endColumn":29,"startRow":61},"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"ref":"SwitchCaseLabelSyntax","name":"label","value":{"text":"SwitchCaseLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"text":"SwitchCase","type":"other","parent":614},{"parent":664,"range":{"endColumn":13,"startRow":61,"startColumn":1,"endRow":61},"type":"other","id":665,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCaseKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndCaseItems"},{"value":{"text":"SwitchCaseItemListSyntax"},"name":"caseItems","ref":"SwitchCaseItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"text":"SwitchCaseLabel"},{"range":{"startRow":61,"startColumn":1,"endColumn":5,"endRow":61},"text":"case","type":"other","id":666,"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>"},"structure":[],"parent":665},{"parent":665,"range":{"startRow":61,"startColumn":6,"endColumn":12,"endRow":61},"type":"collection","id":667,"structure":[{"value":{"text":"SwitchCaseItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"SwitchCaseItemList"},{"parent":667,"range":{"startRow":61,"endRow":61,"startColumn":6,"endColumn":12},"type":"other","id":668,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"SwitchCaseItem"},{"parent":668,"text":"ExpressionPattern","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"pattern","range":{"startRow":61,"startColumn":6,"endRow":61,"endColumn":12},"id":669},{"parent":669,"text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","range":{"startRow":61,"endColumn":12,"startColumn":6,"endRow":61},"id":670},{"parent":670,"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("5")","text":"5"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","range":{"startRow":61,"startColumn":6,"endColumn":7,"endRow":61},"id":671},{"range":{"endColumn":7,"startColumn":6,"startRow":61,"endRow":61},"text":"5","type":"other","id":672,"token":{"kind":"integerLiteral("5")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":671},{"range":{"endColumn":10,"startColumn":7,"startRow":61,"endRow":61},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"text":"..<","kind":"binaryOperator("..<")"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"parent":670,"text":"BinaryOperatorExpr","type":"expr","id":673},{"type":"other","range":{"startRow":61,"startColumn":7,"endRow":61,"endColumn":10},"text":"..<","token":{"kind":"binaryOperator("..<")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":673,"id":674},{"range":{"startRow":61,"startColumn":10,"endRow":61,"endColumn":12},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("12")","text":"12"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"parent":670,"text":"IntegerLiteralExpr","type":"expr","id":675},{"type":"other","range":{"startColumn":10,"startRow":61,"endColumn":12,"endRow":61},"text":"12","token":{"trailingTrivia":"","kind":"integerLiteral("12")","leadingTrivia":""},"structure":[],"parent":675,"id":676},{"type":"other","range":{"startColumn":12,"startRow":61,"endColumn":13,"endRow":61},"text":":","token":{"trailingTrivia":"","kind":"colon","leadingTrivia":""},"structure":[],"parent":665,"id":677},{"range":{"startColumn":5,"startRow":62,"endColumn":29,"endRow":62},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":664,"text":"CodeBlockItemList","type":"collection","id":678},{"range":{"endColumn":29,"startRow":62,"endRow":62,"startColumn":5},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"item","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":678,"text":"CodeBlockItem","type":"other","id":679},{"parent":679,"text":"InfixOperatorExpr","type":"expr","id":680,"range":{"startColumn":5,"endRow":62,"endColumn":29,"startRow":62},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"AssignmentExprSyntax","value":{"text":"AssignmentExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}]},{"parent":680,"text":"DeclReferenceExpr","type":"expr","id":681,"range":{"startColumn":5,"endColumn":17,"startRow":62,"endRow":62},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"naturalCount","kind":"identifier("naturalCount")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","range":{"startRow":62,"endColumn":17,"startColumn":5,"endRow":62},"text":"naturalCount","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("naturalCount")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"parent":681,"id":682},{"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"id":683,"range":{"startRow":62,"endColumn":19,"startColumn":18,"endRow":62},"type":"expr","parent":680,"text":"AssignmentExpr"},{"type":"other","range":{"startColumn":18,"startRow":62,"endRow":62,"endColumn":19},"text":"=","token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"parent":683,"id":684},{"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"id":685,"range":{"startColumn":20,"startRow":62,"endRow":62,"endColumn":29},"type":"expr","parent":680,"text":"StringLiteralExpr"},{"type":"other","range":{"endColumn":21,"endRow":62,"startRow":62,"startColumn":20},"text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":685,"id":686},{"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"id":687,"range":{"endColumn":28,"endRow":62,"startRow":62,"startColumn":21},"text":"StringLiteralSegmentList","parent":685,"type":"collection"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("several")","text":"several"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":688,"range":{"startColumn":21,"startRow":62,"endRow":62,"endColumn":28},"text":"StringSegment","parent":687,"type":"other"},{"type":"other","range":{"startRow":62,"startColumn":21,"endRow":62,"endColumn":28},"text":"several","token":{"leadingTrivia":"","kind":"stringSegment("several")","trailingTrivia":""},"structure":[],"parent":688,"id":689},{"type":"other","range":{"startRow":62,"startColumn":28,"endRow":62,"endColumn":29},"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"structure":[],"parent":685,"id":690},{"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"id":691,"range":{"startRow":63,"startColumn":1,"endRow":64,"endColumn":31},"text":"SwitchCase","parent":614,"type":"other"},{"parent":691,"type":"other","id":692,"range":{"startColumn":1,"endColumn":15,"endRow":63,"startRow":63},"text":"SwitchCaseLabel","structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","ref":"SwitchCaseItemListSyntax","value":{"text":"SwitchCaseItemListSyntax"}},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}]},{"type":"other","range":{"endColumn":5,"startRow":63,"startColumn":1,"endRow":63},"text":"case","token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)","trailingTrivia":"␣<\/span>"},"structure":[],"parent":692,"id":693},{"parent":692,"type":"collection","id":694,"range":{"endColumn":14,"startRow":63,"startColumn":6,"endRow":63},"text":"SwitchCaseItemList","structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"parent":694,"type":"other","id":695,"range":{"endColumn":14,"startRow":63,"endRow":63,"startColumn":6},"text":"SwitchCaseItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"endColumn":14,"startRow":63,"endRow":63,"startColumn":6},"id":696,"parent":695,"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"text":"ExpressionPattern","type":"pattern"},{"range":{"startColumn":6,"startRow":63,"endRow":63,"endColumn":14},"id":697,"parent":696,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"text":"InfixOperatorExpr","type":"expr"},{"range":{"startColumn":6,"endRow":63,"startRow":63,"endColumn":8},"id":698,"parent":697,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"12","kind":"integerLiteral("12")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"text":"IntegerLiteralExpr","type":"expr"},{"type":"other","range":{"endColumn":8,"startColumn":6,"startRow":63,"endRow":63},"text":"12","token":{"trailingTrivia":"","kind":"integerLiteral("12")","leadingTrivia":""},"structure":[],"parent":698,"id":699},{"range":{"endColumn":11,"startColumn":8,"startRow":63,"endRow":63},"parent":697,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("..<")","text":"..<"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","text":"BinaryOperatorExpr","id":700},{"type":"other","range":{"endRow":63,"endColumn":11,"startRow":63,"startColumn":8},"text":"..<","token":{"leadingTrivia":"","trailingTrivia":"","kind":"binaryOperator("..<")"},"structure":[],"parent":700,"id":701},{"range":{"endRow":63,"endColumn":14,"startRow":63,"startColumn":11},"parent":697,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("100")","text":"100"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","text":"IntegerLiteralExpr","id":702},{"type":"other","range":{"startColumn":11,"startRow":63,"endColumn":14,"endRow":63},"text":"100","token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("100")"},"structure":[],"parent":702,"id":703},{"type":"other","range":{"startColumn":14,"startRow":63,"endColumn":15,"endRow":63},"text":":","token":{"trailingTrivia":"","leadingTrivia":"","kind":"colon"},"structure":[],"parent":692,"id":704},{"range":{"startColumn":5,"startRow":64,"endColumn":31,"endRow":64},"parent":691,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","text":"CodeBlockItemList","id":705},{"range":{"startColumn":5,"startRow":64,"endColumn":31,"endRow":64},"parent":705,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":706},{"range":{"endColumn":31,"startColumn":5,"startRow":64,"endRow":64},"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"rightOperand","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","parent":706,"id":707,"text":"InfixOperatorExpr"},{"range":{"startColumn":5,"startRow":64,"endColumn":17,"endRow":64},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("naturalCount")","text":"naturalCount"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","parent":707,"id":708,"text":"DeclReferenceExpr"},{"type":"other","text":"naturalCount","range":{"startColumn":5,"startRow":64,"endRow":64,"endColumn":17},"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("naturalCount")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"parent":708,"id":709},{"id":710,"text":"AssignmentExpr","type":"expr","range":{"startColumn":18,"startRow":64,"endRow":64,"endColumn":19},"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"parent":707},{"type":"other","text":"=","range":{"endRow":64,"startColumn":18,"startRow":64,"endColumn":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"structure":[],"parent":710,"id":711},{"id":712,"text":"StringLiteralExpr","type":"expr","range":{"endRow":64,"startColumn":20,"startRow":64,"endColumn":31},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"parent":707},{"type":"other","range":{"startColumn":20,"endRow":64,"endColumn":21,"startRow":64},"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"structure":[],"parent":712,"id":713},{"range":{"startColumn":21,"endRow":64,"endColumn":30,"startRow":64},"id":714,"parent":712,"text":"StringLiteralSegmentList","type":"collection","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endColumn":30,"startRow":64,"endRow":64,"startColumn":21},"id":715,"parent":714,"text":"StringSegment","type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("dozens of")","text":"dozens of"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"type":"other","range":{"startColumn":21,"endColumn":30,"endRow":64,"startRow":64},"text":"dozens␣<\/span>of","token":{"trailingTrivia":"","kind":"stringSegment("dozens of")","leadingTrivia":""},"structure":[],"parent":715,"id":716},{"type":"other","range":{"startColumn":30,"endColumn":31,"endRow":64,"startRow":64},"text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"structure":[],"parent":712,"id":717},{"range":{"startColumn":1,"endColumn":33,"endRow":66,"startRow":65},"id":718,"parent":614,"text":"SwitchCase","type":"other","structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}]},{"parent":718,"range":{"endColumn":17,"startColumn":1,"startRow":65,"endRow":65},"text":"SwitchCaseLabel","structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","ref":"SwitchCaseItemListSyntax","value":{"text":"SwitchCaseItemListSyntax"}},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"type":"other","id":719},{"type":"other","range":{"endRow":65,"startColumn":1,"startRow":65,"endColumn":5},"text":"case","token":{"kind":"keyword(SwiftSyntax.Keyword.case)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"structure":[],"parent":719,"id":720},{"parent":719,"range":{"endRow":65,"startColumn":6,"startRow":65,"endColumn":16},"text":"SwitchCaseItemList","structure":[{"value":{"text":"SwitchCaseItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","id":721},{"parent":721,"range":{"startRow":65,"endColumn":16,"endRow":65,"startColumn":6},"text":"SwitchCaseItem","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","id":722},{"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"ref":"InfixOperatorExprSyntax","name":"expression","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"pattern","text":"ExpressionPattern","range":{"endColumn":16,"startRow":65,"endRow":65,"startColumn":6},"id":723,"parent":722},{"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","text":"InfixOperatorExpr","range":{"endColumn":16,"startRow":65,"endRow":65,"startColumn":6},"id":724,"parent":723},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"100","kind":"integerLiteral("100")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","range":{"startRow":65,"endRow":65,"startColumn":6,"endColumn":9},"id":725,"parent":724},{"type":"other","range":{"endColumn":9,"startRow":65,"endRow":65,"startColumn":6},"text":"100","token":{"leadingTrivia":"","kind":"integerLiteral("100")","trailingTrivia":""},"structure":[],"parent":725,"id":726},{"range":{"endColumn":12,"startRow":65,"endRow":65,"startColumn":9},"id":727,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("..<")","text":"..<"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","parent":724,"text":"BinaryOperatorExpr"},{"type":"other","range":{"startRow":65,"startColumn":9,"endColumn":12,"endRow":65},"text":"..<","token":{"leadingTrivia":"","kind":"binaryOperator("..<")","trailingTrivia":""},"structure":[],"parent":727,"id":728},{"range":{"startRow":65,"startColumn":12,"endColumn":16,"endRow":65},"id":729,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"1000","kind":"integerLiteral("1000")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","parent":724,"text":"IntegerLiteralExpr"},{"text":"1000","parent":729,"id":730,"type":"other","token":{"trailingTrivia":"","kind":"integerLiteral("1000")","leadingTrivia":""},"range":{"startRow":65,"endRow":65,"endColumn":16,"startColumn":12},"structure":[]},{"text":":","parent":719,"id":731,"type":"other","token":{"trailingTrivia":"","kind":"colon","leadingTrivia":""},"range":{"startRow":65,"endRow":65,"endColumn":17,"startColumn":16},"structure":[]},{"range":{"startRow":66,"endRow":66,"endColumn":33,"startColumn":5},"id":732,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","parent":718,"text":"CodeBlockItemList"},{"range":{"startRow":66,"startColumn":5,"endColumn":33,"endRow":66},"id":733,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","parent":732,"text":"CodeBlockItem"},{"parent":733,"text":"InfixOperatorExpr","type":"expr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"rightOperand","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"range":{"startRow":66,"endRow":66,"endColumn":33,"startColumn":5},"id":734},{"parent":734,"text":"DeclReferenceExpr","type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"naturalCount","kind":"identifier("naturalCount")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"range":{"startRow":66,"startColumn":5,"endColumn":17,"endRow":66},"id":735},{"text":"naturalCount","parent":735,"id":736,"type":"other","token":{"kind":"identifier("naturalCount")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"startColumn":5,"endRow":66,"endColumn":17,"startRow":66},"structure":[]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"range":{"endRow":66,"startColumn":18,"endColumn":19,"startRow":66},"parent":734,"text":"AssignmentExpr","id":737,"type":"expr"},{"text":"=","parent":737,"id":738,"type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"equal"},"range":{"startColumn":18,"endColumn":19,"endRow":66,"startRow":66},"structure":[]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"range":{"startColumn":20,"endColumn":33,"endRow":66,"startRow":66},"parent":734,"text":"StringLiteralExpr","id":739,"type":"expr"},{"text":""","parent":739,"id":740,"type":"other","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"endRow":66,"endColumn":21,"startColumn":20,"startRow":66},"structure":[]},{"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":741,"parent":739,"text":"StringLiteralSegmentList","range":{"startColumn":21,"endColumn":32,"endRow":66,"startRow":66}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"hundreds of","kind":"stringSegment("hundreds of")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","id":742,"parent":741,"text":"StringSegment","range":{"startRow":66,"startColumn":21,"endColumn":32,"endRow":66}},{"text":"hundreds␣<\/span>of","parent":742,"id":743,"type":"other","token":{"leadingTrivia":"","kind":"stringSegment("hundreds of")","trailingTrivia":""},"range":{"endRow":66,"endColumn":32,"startColumn":21,"startRow":66},"structure":[]},{"text":""","parent":739,"id":744,"type":"other","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"range":{"endRow":66,"endColumn":33,"startColumn":32,"startRow":66},"structure":[]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeAndLabel"},{"ref":"SwitchDefaultLabelSyntax","value":{"text":"SwitchDefaultLabelSyntax"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedAfterStatements"}],"type":"other","id":745,"parent":614,"text":"SwitchCase","range":{"endRow":68,"endColumn":26,"startColumn":1,"startRow":67}},{"structure":[{"name":"unexpectedBeforeDefaultKeyword","value":{"text":"nil"}},{"name":"defaultKeyword","value":{"text":"default","kind":"keyword(SwiftSyntax.Keyword.default)"}},{"name":"unexpectedBetweenDefaultKeywordAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"type":"other","id":746,"parent":745,"text":"SwitchDefaultLabel","range":{"startRow":67,"endRow":67,"endColumn":9,"startColumn":1}},{"text":"default","parent":746,"id":747,"type":"other","token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.default)","trailingTrivia":""},"range":{"endRow":67,"startColumn":1,"startRow":67,"endColumn":8},"structure":[]},{"text":":","parent":746,"id":748,"type":"other","token":{"leadingTrivia":"","kind":"colon","trailingTrivia":""},"range":{"endRow":67,"startColumn":8,"startRow":67,"endColumn":9},"structure":[]},{"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":749,"type":"collection","parent":745,"range":{"endRow":68,"startColumn":5,"startRow":68,"endColumn":26},"text":"CodeBlockItemList"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":750,"type":"other","parent":749,"range":{"startRow":68,"endColumn":26,"endRow":68,"startColumn":5},"text":"CodeBlockItem"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"AssignmentExprSyntax"},"ref":"AssignmentExprSyntax","name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"id":751,"type":"expr","parent":750,"range":{"endColumn":26,"startRow":68,"startColumn":5,"endRow":68},"text":"InfixOperatorExpr"},{"id":752,"parent":751,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("naturalCount")","text":"naturalCount"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","text":"DeclReferenceExpr","range":{"startRow":68,"endRow":68,"startColumn":5,"endColumn":17}},{"text":"naturalCount","parent":752,"id":753,"type":"other","token":{"kind":"identifier("naturalCount")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endRow":68,"startRow":68,"startColumn":5,"endColumn":17},"structure":[]},{"id":754,"parent":751,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"type":"expr","text":"AssignmentExpr","range":{"endRow":68,"startRow":68,"startColumn":18,"endColumn":19}},{"text":"=","parent":754,"id":755,"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"range":{"startColumn":18,"endColumn":19,"startRow":68,"endRow":68},"structure":[]},{"text":"StringLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"id":756,"range":{"startRow":68,"startColumn":20,"endRow":68,"endColumn":26},"parent":751,"type":"expr"},{"text":""","parent":756,"id":757,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":68,"endColumn":21,"endRow":68,"startColumn":20},"structure":[]},{"text":"StringLiteralSegmentList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":758,"range":{"startRow":68,"endColumn":25,"endRow":68,"startColumn":21},"parent":756,"type":"collection"},{"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"name":"content","value":{"kind":"stringSegment("many")","text":"many"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":759,"range":{"startColumn":21,"startRow":68,"endRow":68,"endColumn":25},"parent":758,"type":"other"},{"text":"many","parent":759,"id":760,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("many")"},"range":{"endColumn":25,"startRow":68,"endRow":68,"startColumn":21},"structure":[]},{"text":""","parent":756,"id":761,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"endColumn":26,"startRow":68,"endRow":68,"startColumn":25},"structure":[]},{"text":"}","parent":609,"id":762,"type":"other","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"endColumn":2,"startRow":69,"endRow":69,"startColumn":1},"structure":[]},{"text":"CodeBlockItem","id":763,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"name":"item","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","range":{"endColumn":53,"startRow":70,"endRow":70,"startColumn":1},"parent":1},{"text":"FunctionCallExpr","id":764,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","range":{"startRow":70,"endColumn":53,"startColumn":1,"endRow":70},"parent":763},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":765,"type":"expr","range":{"startColumn":1,"endRow":70,"endColumn":6,"startRow":70},"parent":764,"text":"DeclReferenceExpr"},{"text":"print","parent":765,"id":766,"type":"other","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"startRow":70,"startColumn":1,"endColumn":6,"endRow":70},"structure":[]},{"text":"(","parent":764,"id":767,"type":"other","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":70,"startColumn":6,"endColumn":7,"endRow":70},"structure":[]},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":768,"type":"collection","range":{"startRow":70,"startColumn":7,"endColumn":52,"endRow":70},"parent":764,"text":"LabeledExprList"},{"id":769,"parent":768,"text":"LabeledExpr","range":{"endRow":70,"endColumn":52,"startRow":70,"startColumn":7},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"id":770,"parent":769,"text":"StringLiteralExpr","range":{"endColumn":52,"startRow":70,"startColumn":7,"endRow":70},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr"},{"text":""","parent":770,"id":771,"type":"other","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":70,"startColumn":7,"endColumn":8,"endRow":70},"structure":[]},{"type":"collection","id":772,"parent":770,"text":"StringLiteralSegmentList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}],"range":{"startRow":70,"startColumn":8,"endColumn":51,"endRow":70}},{"type":"other","id":773,"parent":772,"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"There are ","kind":"stringSegment("There are ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"range":{"endColumn":18,"startRow":70,"endRow":70,"startColumn":8}},{"text":"There␣<\/span>are␣<\/span>","parent":773,"id":774,"type":"other","token":{"kind":"stringSegment("There are ")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":18,"endRow":70,"startRow":70,"startColumn":8},"structure":[]},{"type":"other","id":775,"parent":772,"text":"ExpressionSegment","structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"range":{"endColumn":33,"endRow":70,"startRow":70,"startColumn":18}},{"text":"\\","parent":775,"id":776,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"range":{"startColumn":18,"endRow":70,"endColumn":19,"startRow":70},"structure":[]},{"text":"(","parent":775,"id":777,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"startColumn":19,"endRow":70,"endColumn":20,"startRow":70},"structure":[]},{"parent":775,"text":"LabeledExprList","range":{"startColumn":20,"endRow":70,"endColumn":32,"startRow":70},"id":778,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"parent":778,"text":"LabeledExpr","range":{"startColumn":20,"endRow":70,"endColumn":32,"startRow":70},"id":779,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"parent":779,"range":{"endRow":70,"endColumn":32,"startRow":70,"startColumn":20},"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"naturalCount","kind":"identifier("naturalCount")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":780,"type":"expr"},{"id":781,"token":{"leadingTrivia":"","kind":"identifier("naturalCount")","trailingTrivia":""},"text":"naturalCount","parent":780,"range":{"endColumn":32,"endRow":70,"startRow":70,"startColumn":20},"type":"other","structure":[]},{"id":782,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"text":")","parent":775,"range":{"endColumn":33,"endRow":70,"startRow":70,"startColumn":32},"type":"other","structure":[]},{"parent":772,"range":{"endColumn":34,"endRow":70,"startRow":70,"startColumn":33},"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(" ")","text":" "}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":783,"type":"other"},{"id":784,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment(" ")"},"text":"␣<\/span>","parent":783,"range":{"endRow":70,"startRow":70,"endColumn":34,"startColumn":33},"type":"other","structure":[]},{"range":{"endRow":70,"endColumn":50,"startRow":70,"startColumn":34},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"text":"ExpressionSegment","id":785,"type":"other","parent":772},{"id":786,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"text":"\\","parent":785,"range":{"endColumn":35,"startRow":70,"startColumn":34,"endRow":70},"type":"other","structure":[]},{"id":787,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"text":"(","parent":785,"range":{"endColumn":36,"startRow":70,"startColumn":35,"endRow":70},"type":"other","structure":[]},{"range":{"endColumn":49,"startRow":70,"startColumn":36,"endRow":70},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"LabeledExprList","id":788,"type":"collection","parent":785},{"range":{"endRow":70,"startRow":70,"startColumn":36,"endColumn":49},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"LabeledExpr","id":789,"type":"other","parent":788},{"id":790,"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"countedThings","kind":"identifier("countedThings")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":789,"text":"DeclReferenceExpr","range":{"startRow":70,"endRow":70,"endColumn":49,"startColumn":36}},{"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("countedThings")"},"text":"countedThings","parent":790,"type":"other","range":{"endColumn":49,"startRow":70,"startColumn":36,"endRow":70},"id":791},{"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","parent":785,"type":"other","range":{"endColumn":50,"startRow":70,"startColumn":49,"endRow":70},"id":792},{"id":793,"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"name":"content","value":{"text":".","kind":"stringSegment(".")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"parent":772,"text":"StringSegment","range":{"endColumn":51,"startRow":70,"startColumn":50,"endRow":70}},{"structure":[],"token":{"leadingTrivia":"","kind":"stringSegment(".")","trailingTrivia":""},"text":".","parent":793,"range":{"endColumn":51,"startColumn":50,"startRow":70,"endRow":70},"type":"other","id":794},{"structure":[],"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"text":""","parent":770,"range":{"endColumn":52,"startColumn":51,"startRow":70,"endRow":70},"type":"other","id":795},{"structure":[],"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"text":")","parent":764,"range":{"endColumn":53,"startColumn":52,"startRow":70,"endRow":70},"type":"other","id":796},{"text":"MultipleTrailingClosureElementList","id":797,"range":{"endColumn":53,"startColumn":53,"startRow":70,"endRow":70},"type":"collection","parent":764,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"text":"CodeBlockItem","id":798,"range":{"startRow":73,"endColumn":23,"startColumn":1,"endRow":73},"type":"other","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"text":"VariableDecl","id":799,"range":{"startColumn":1,"endRow":73,"startRow":73,"endColumn":23},"type":"decl","parent":798,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax","name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}]},{"range":{"startColumn":53,"endColumn":53,"startRow":70,"endRow":70},"parent":799,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":800,"type":"collection","text":"AttributeList"},{"range":{"startRow":70,"startColumn":53,"endRow":70,"endColumn":53},"parent":799,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":801,"type":"collection","text":"DeclModifierList"},{"id":802,"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>Switch␣<\/span>with␣<\/span>tuple␣<\/span>matching<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"text":"let","parent":799,"range":{"startColumn":1,"endColumn":4,"startRow":73,"endRow":73},"type":"other","structure":[]},{"range":{"startColumn":5,"endColumn":23,"startRow":73,"endRow":73},"parent":799,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":803,"type":"collection","text":"PatternBindingList"},{"range":{"startColumn":5,"endRow":73,"endColumn":23,"startRow":73},"parent":803,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"name":"initializer","ref":"InitializerClauseSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":804,"type":"other","text":"PatternBinding"},{"parent":804,"text":"IdentifierPattern","structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"somePoint","kind":"identifier("somePoint")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"type":"pattern","range":{"endColumn":14,"startColumn":5,"startRow":73,"endRow":73},"id":805},{"id":806,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("somePoint")"},"text":"somePoint","parent":805,"type":"other","range":{"endRow":73,"startColumn":5,"startRow":73,"endColumn":14},"structure":[]},{"parent":804,"text":"InitializerClause","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"TupleExprSyntax"},"ref":"TupleExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"type":"other","range":{"endRow":73,"startColumn":15,"startRow":73,"endColumn":23},"id":807},{"id":808,"token":{"leadingTrivia":"","kind":"equal","trailingTrivia":"␣<\/span>"},"text":"=","parent":807,"range":{"endRow":73,"endColumn":16,"startRow":73,"startColumn":15},"type":"other","structure":[]},{"parent":807,"range":{"endRow":73,"endColumn":23,"startRow":73,"startColumn":17},"text":"TupleExpr","structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenElementsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":809,"type":"expr"},{"id":810,"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"text":"(","parent":809,"range":{"startRow":73,"startColumn":17,"endColumn":18,"endRow":73},"type":"other","structure":[]},{"parent":809,"range":{"startRow":73,"startColumn":18,"endColumn":22,"endRow":73},"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":811,"type":"collection"},{"parent":811,"range":{"startColumn":18,"startRow":73,"endRow":73,"endColumn":20},"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"expression","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":812,"type":"other"},{"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("1")","text":"1"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","parent":812,"range":{"endColumn":19,"startRow":73,"endRow":73,"startColumn":18},"id":813},{"id":814,"token":{"leadingTrivia":"","kind":"integerLiteral("1")","trailingTrivia":""},"text":"1","parent":813,"type":"other","range":{"startColumn":18,"endRow":73,"startRow":73,"endColumn":19},"structure":[]},{"id":815,"token":{"leadingTrivia":"","kind":"comma","trailingTrivia":"␣<\/span>"},"text":",","parent":812,"type":"other","range":{"startColumn":19,"endRow":73,"startRow":73,"endColumn":20},"structure":[]},{"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":811,"range":{"startColumn":21,"endRow":73,"startRow":73,"endColumn":22},"id":816},{"range":{"startColumn":21,"endRow":73,"startRow":73,"endColumn":22},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("1")","text":"1"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","id":817,"parent":816,"text":"IntegerLiteralExpr"},{"id":818,"token":{"leadingTrivia":"","kind":"integerLiteral("1")","trailingTrivia":""},"text":"1","parent":817,"range":{"startRow":73,"endRow":73,"endColumn":22,"startColumn":21},"type":"other","structure":[]},{"id":819,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"text":")","parent":809,"range":{"startRow":73,"endRow":73,"endColumn":23,"startColumn":22},"type":"other","structure":[]},{"range":{"startRow":74,"endRow":85,"endColumn":2,"startColumn":1},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"ExpressionStmtSyntax"},"ref":"ExpressionStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","id":820,"parent":1,"text":"CodeBlockItem"},{"text":"ExpressionStmt","parent":820,"id":821,"range":{"endColumn":2,"startColumn":1,"startRow":74,"endRow":85},"type":"other","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"ref":"SwitchExprSyntax","name":"expression","value":{"text":"SwitchExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"text":"SwitchExpr","parent":821,"id":822,"range":{"startColumn":1,"startRow":74,"endRow":85,"endColumn":2},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeSwitchKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.switch)","text":"switch"},"name":"switchKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenSwitchKeywordAndSubject"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"subject"},{"value":{"text":"nil"},"name":"unexpectedBetweenSubjectAndLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndCases"},{"value":{"text":"SwitchCaseListSyntax"},"ref":"SwitchCaseListSyntax","name":"cases"},{"value":{"text":"nil"},"name":"unexpectedBetweenCasesAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"structure":[],"token":{"leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.switch)","trailingTrivia":"␣<\/span>"},"text":"switch","parent":822,"range":{"endColumn":7,"startColumn":1,"startRow":74,"endRow":74},"type":"other","id":823},{"range":{"endRow":74,"startColumn":8,"startRow":74,"endColumn":17},"parent":822,"id":824,"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("somePoint")","text":"somePoint"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"structure":[],"token":{"leadingTrivia":"","kind":"identifier("somePoint")","trailingTrivia":"␣<\/span>"},"text":"somePoint","parent":824,"range":{"endColumn":17,"startRow":74,"endRow":74,"startColumn":8},"type":"other","id":825},{"structure":[],"token":{"leadingTrivia":"","kind":"leftBrace","trailingTrivia":""},"text":"{","parent":822,"range":{"endColumn":19,"startRow":74,"endRow":74,"startColumn":18},"type":"other","id":826},{"range":{"endColumn":68,"startRow":75,"endRow":84,"startColumn":1},"parent":822,"id":827,"text":"SwitchCaseList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}],"type":"collection"},{"range":{"endColumn":37,"startRow":75,"startColumn":1,"endRow":76},"parent":827,"id":828,"text":"SwitchCase","structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"SwitchCaseLabelSyntax"},"ref":"SwitchCaseLabelSyntax"},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other"},{"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCaseKeyword"},{"value":{"text":"case","kind":"keyword(SwiftSyntax.Keyword.case)"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndCaseItems"},{"value":{"text":"SwitchCaseItemListSyntax"},"name":"caseItems","ref":"SwitchCaseItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"text":"SwitchCaseLabel","range":{"startRow":75,"endColumn":13,"endRow":75,"startColumn":1},"parent":828,"id":829},{"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>"},"parent":829,"id":830,"range":{"endRow":75,"endColumn":5,"startRow":75,"startColumn":1},"type":"other","structure":[],"text":"case"},{"type":"collection","structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"text":"SwitchCaseItemList","range":{"endRow":75,"endColumn":12,"startRow":75,"startColumn":6},"parent":829,"id":831},{"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"ExpressionPatternSyntax"},"name":"pattern","ref":"ExpressionPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"SwitchCaseItem","range":{"endColumn":12,"startRow":75,"startColumn":6,"endRow":75},"parent":831,"id":832},{"id":833,"type":"pattern","parent":832,"range":{"startColumn":6,"endRow":75,"startRow":75,"endColumn":12},"text":"ExpressionPattern","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"TupleExprSyntax","value":{"text":"TupleExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"id":834,"type":"expr","parent":833,"range":{"startRow":75,"startColumn":6,"endRow":75,"endColumn":12},"text":"TupleExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"value":{"text":"LabeledExprListSyntax"},"name":"elements","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}]},{"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"id":835,"parent":834,"range":{"startRow":75,"endColumn":7,"startColumn":6,"endRow":75},"type":"other","text":"(","structure":[]},{"id":836,"type":"collection","parent":834,"range":{"startRow":75,"endColumn":11,"startColumn":7,"endRow":75},"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"LabeledExpr","range":{"startColumn":7,"endRow":75,"startRow":75,"endColumn":9},"id":837,"type":"other","parent":836},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"text":"IntegerLiteralExpr","range":{"startRow":75,"startColumn":7,"endRow":75,"endColumn":8},"id":838,"type":"expr","parent":837},{"token":{"kind":"integerLiteral("0")","leadingTrivia":"","trailingTrivia":""},"id":839,"parent":838,"range":{"startRow":75,"endRow":75,"endColumn":8,"startColumn":7},"type":"other","structure":[],"text":"0"},{"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":840,"parent":837,"range":{"startRow":75,"endRow":75,"endColumn":9,"startColumn":8},"type":"other","structure":[],"text":","},{"text":"LabeledExpr","range":{"endRow":75,"endColumn":11,"startColumn":10,"startRow":75},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","parent":836,"id":841},{"range":{"endColumn":11,"startColumn":10,"endRow":75,"startRow":75},"parent":841,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("0")","text":"0"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"text":"IntegerLiteralExpr","id":842,"type":"expr"},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("0")"},"parent":842,"id":843,"range":{"startColumn":10,"endColumn":11,"startRow":75,"endRow":75},"type":"other","structure":[],"text":"0"},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"parent":834,"id":844,"range":{"startColumn":11,"endColumn":12,"startRow":75,"endRow":75},"type":"other","structure":[],"text":")"},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"colon"},"parent":829,"id":845,"range":{"startColumn":12,"endColumn":13,"startRow":75,"endRow":75},"type":"other","structure":[],"text":":"},{"range":{"startColumn":5,"endColumn":37,"startRow":76,"endRow":76},"parent":828,"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"CodeBlockItemList","id":846,"type":"collection"},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":847,"range":{"endColumn":37,"endRow":76,"startColumn":5,"startRow":76},"text":"CodeBlockItem","type":"other","parent":846},{"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":848,"range":{"endColumn":37,"startRow":76,"endRow":76,"startColumn":5},"text":"FunctionCallExpr","type":"expr","parent":847},{"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":848,"id":849,"range":{"endRow":76,"startColumn":5,"endColumn":10,"startRow":76},"type":"expr"},{"token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":849,"id":850,"range":{"startColumn":5,"startRow":76,"endRow":76,"endColumn":10},"type":"other","text":"print","structure":[]},{"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"parent":848,"id":851,"range":{"startColumn":10,"startRow":76,"endRow":76,"endColumn":11},"type":"other","text":"(","structure":[]},{"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":848,"id":852,"range":{"startColumn":11,"startRow":76,"endRow":76,"endColumn":36},"type":"collection"},{"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"expression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":852,"id":853,"range":{"startColumn":11,"startRow":76,"endRow":76,"endColumn":36},"type":"other"},{"id":854,"parent":853,"type":"expr","text":"StringLiteralExpr","structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"range":{"endColumn":36,"startRow":76,"endRow":76,"startColumn":11}},{"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"id":855,"parent":854,"range":{"startRow":76,"endRow":76,"endColumn":12,"startColumn":11},"type":"other","text":""","structure":[]},{"id":856,"parent":854,"range":{"endRow":76,"startColumn":12,"startRow":76,"endColumn":35},"text":"StringLiteralSegmentList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"id":857,"parent":856,"range":{"endColumn":35,"startColumn":12,"startRow":76,"endRow":76},"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("(0, 0) is at the origin")","text":"(0, 0) is at the origin"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other"},{"token":{"leadingTrivia":"","kind":"stringSegment("(0, 0) is at the origin")","trailingTrivia":""},"id":858,"parent":857,"range":{"startRow":76,"endRow":76,"endColumn":35,"startColumn":12},"type":"other","text":"(0,␣<\/span>0)␣<\/span>is␣<\/span>at␣<\/span>the␣<\/span>origin","structure":[]},{"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"id":859,"parent":854,"range":{"startRow":76,"endRow":76,"endColumn":36,"startColumn":35},"type":"other","text":""","structure":[]},{"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"id":860,"parent":848,"range":{"startRow":76,"endRow":76,"endColumn":37,"startColumn":36},"type":"other","text":")","structure":[]},{"id":861,"parent":848,"range":{"startRow":76,"endRow":76,"endColumn":37,"startColumn":37},"text":"MultipleTrailingClosureElementList","structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection"},{"id":862,"parent":827,"range":{"endRow":78,"startColumn":1,"startRow":77,"endColumn":50},"text":"SwitchCase","structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"SwitchCaseLabelSyntax"},"ref":"SwitchCaseLabelSyntax"},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other"},{"text":"SwitchCaseLabel","type":"other","range":{"startColumn":1,"endColumn":13,"startRow":77,"endRow":77},"id":863,"parent":862,"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"text":"case","kind":"keyword(SwiftSyntax.Keyword.case)"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","ref":"SwitchCaseItemListSyntax","value":{"text":"SwitchCaseItemListSyntax"}},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}]},{"token":{"kind":"keyword(SwiftSyntax.Keyword.case)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"id":864,"parent":863,"range":{"endColumn":5,"startColumn":1,"endRow":77,"startRow":77},"type":"other","text":"case","structure":[]},{"text":"SwitchCaseItemList","type":"collection","range":{"endColumn":12,"startColumn":6,"endRow":77,"startRow":77},"id":865,"parent":863,"structure":[{"value":{"text":"SwitchCaseItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"text":"SwitchCaseItem","type":"other","range":{"startColumn":6,"endRow":77,"endColumn":12,"startRow":77},"id":866,"parent":865,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"id":867,"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"TupleExprSyntax","value":{"text":"TupleExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"range":{"startRow":77,"startColumn":6,"endColumn":12,"endRow":77},"type":"pattern","text":"ExpressionPattern","parent":866},{"id":868,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndElements","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"elements","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenElementsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"range":{"startRow":77,"endColumn":12,"startColumn":6,"endRow":77},"type":"expr","text":"TupleExpr","parent":867},{"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"id":869,"parent":868,"range":{"startRow":77,"startColumn":6,"endRow":77,"endColumn":7},"type":"other","structure":[],"text":"("},{"parent":868,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"id":870,"text":"LabeledExprList","range":{"endRow":77,"startRow":77,"startColumn":7,"endColumn":11},"type":"collection"},{"parent":870,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DiscardAssignmentExprSyntax"},"ref":"DiscardAssignmentExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":871,"text":"LabeledExpr","range":{"startColumn":7,"endColumn":9,"startRow":77,"endRow":77},"type":"other"},{"parent":871,"structure":[{"name":"unexpectedBeforeWildcard","value":{"text":"nil"}},{"name":"wildcard","value":{"text":"_","kind":"wildcard"}},{"name":"unexpectedAfterWildcard","value":{"text":"nil"}}],"id":872,"text":"DiscardAssignmentExpr","range":{"startRow":77,"endRow":77,"startColumn":7,"endColumn":8},"type":"expr"},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"wildcard"},"parent":872,"id":873,"range":{"startRow":77,"endRow":77,"endColumn":8,"startColumn":7},"type":"other","structure":[],"text":"_"},{"token":{"leadingTrivia":"","kind":"comma","trailingTrivia":"␣<\/span>"},"parent":871,"id":874,"range":{"startRow":77,"endRow":77,"endColumn":9,"startColumn":8},"type":"other","text":",","structure":[]},{"parent":870,"range":{"startRow":77,"endRow":77,"endColumn":11,"startColumn":10},"type":"other","id":875,"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"parent":875,"range":{"endRow":77,"startColumn":10,"startRow":77,"endColumn":11},"type":"expr","id":876,"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"token":{"kind":"integerLiteral("0")","trailingTrivia":"","leadingTrivia":""},"parent":876,"id":877,"range":{"endRow":77,"startRow":77,"startColumn":10,"endColumn":11},"type":"other","text":"0","structure":[]},{"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"parent":868,"id":878,"range":{"endRow":77,"startRow":77,"startColumn":11,"endColumn":12},"type":"other","text":")","structure":[]},{"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":""},"id":879,"parent":863,"range":{"startColumn":12,"endColumn":13,"endRow":77,"startRow":77},"type":"other","structure":[],"text":":"},{"range":{"startColumn":5,"endColumn":50,"endRow":78,"startRow":78},"type":"collection","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":880,"parent":862,"text":"CodeBlockItemList"},{"range":{"endColumn":50,"endRow":78,"startColumn":5,"startRow":78},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":881,"parent":880,"text":"CodeBlockItem"},{"range":{"endColumn":50,"startRow":78,"endRow":78,"startColumn":5},"type":"expr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":882,"parent":881,"text":"FunctionCallExpr"},{"parent":882,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":883,"type":"expr","range":{"startRow":78,"startColumn":5,"endRow":78,"endColumn":10},"text":"DeclReferenceExpr"},{"token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"parent":883,"id":884,"range":{"endColumn":10,"startRow":78,"startColumn":5,"endRow":78},"type":"other","structure":[],"text":"print"},{"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"text":"(","id":885,"range":{"endColumn":11,"startRow":78,"startColumn":10,"endRow":78},"structure":[],"type":"other","parent":882},{"parent":882,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":886,"type":"collection","range":{"endColumn":49,"startRow":78,"startColumn":11,"endRow":78},"text":"LabeledExprList"},{"parent":886,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":887,"type":"other","range":{"startRow":78,"startColumn":11,"endRow":78,"endColumn":49},"text":"LabeledExpr"},{"text":"StringLiteralExpr","type":"expr","range":{"endColumn":49,"endRow":78,"startColumn":11,"startRow":78},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":888,"parent":887},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","id":889,"range":{"endColumn":12,"startColumn":11,"startRow":78,"endRow":78},"structure":[],"type":"other","parent":888},{"range":{"endColumn":48,"startColumn":12,"startRow":78,"endRow":78},"text":"StringLiteralSegmentList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"id":890,"type":"collection","parent":888},{"range":{"startRow":78,"endColumn":13,"startColumn":12,"endRow":78},"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"(","kind":"stringSegment("(")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":891,"type":"other","parent":890},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("(")"},"text":"(","id":892,"range":{"startRow":78,"endColumn":13,"endRow":78,"startColumn":12},"structure":[],"type":"other","parent":891},{"range":{"startRow":78,"endColumn":27,"endRow":78,"startColumn":13},"text":"ExpressionSegment","structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":893,"type":"other","parent":890},{"token":{"leadingTrivia":"","kind":"backslash","trailingTrivia":""},"text":"\\","id":894,"range":{"endRow":78,"endColumn":14,"startRow":78,"startColumn":13},"structure":[],"type":"other","parent":893},{"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"text":"(","id":895,"range":{"endRow":78,"endColumn":15,"startRow":78,"startColumn":14},"structure":[],"type":"other","parent":893},{"parent":893,"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":896,"range":{"endRow":78,"endColumn":26,"startRow":78,"startColumn":15},"type":"collection"},{"parent":896,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":897,"range":{"startColumn":15,"endRow":78,"startRow":78,"endColumn":26},"type":"other"},{"range":{"endRow":78,"endColumn":26,"startColumn":15,"startRow":78},"text":"MemberAccessExpr","parent":897,"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"base","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"type":"expr","id":898},{"range":{"startRow":78,"endRow":78,"endColumn":24,"startColumn":15},"text":"DeclReferenceExpr","parent":898,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"somePoint","kind":"identifier("somePoint")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","id":899},{"token":{"kind":"identifier("somePoint")","leadingTrivia":"","trailingTrivia":""},"text":"somePoint","id":900,"range":{"startColumn":15,"endColumn":24,"endRow":78,"startRow":78},"structure":[],"type":"other","parent":899},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"},"text":".","id":901,"range":{"startColumn":24,"endRow":78,"endColumn":25,"startRow":78},"structure":[],"type":"other","parent":898},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"integerLiteral("0")","text":"0"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","parent":898,"id":902,"text":"DeclReferenceExpr","range":{"startColumn":25,"endRow":78,"endColumn":26,"startRow":78}},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("0")"},"text":"0","id":903,"range":{"startColumn":25,"endRow":78,"endColumn":26,"startRow":78},"structure":[],"type":"other","parent":902},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","id":904,"range":{"startColumn":26,"endRow":78,"endColumn":27,"startRow":78},"structure":[],"type":"other","parent":893},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(", 0) is on the x-axis")","text":", 0) is on the x-axis"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","parent":890,"id":905,"text":"StringSegment","range":{"startColumn":27,"endRow":78,"endColumn":48,"startRow":78}},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(", 0) is on the x-axis")"},"text":",␣<\/span>0)␣<\/span>is␣<\/span>on␣<\/span>the␣<\/span>x-axis","id":906,"range":{"startColumn":27,"endColumn":48,"endRow":78,"startRow":78},"structure":[],"type":"other","parent":905},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","id":907,"range":{"startColumn":48,"endColumn":49,"endRow":78,"startRow":78},"structure":[],"type":"other","parent":888},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","id":908,"range":{"startColumn":49,"endColumn":50,"endRow":78,"startRow":78},"structure":[],"type":"other","parent":882},{"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","parent":882,"id":909,"text":"MultipleTrailingClosureElementList","range":{"startColumn":50,"endColumn":50,"endRow":78,"startRow":78}},{"parent":827,"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other","text":"SwitchCase","id":910,"range":{"startColumn":1,"endColumn":50,"startRow":79,"endRow":80}},{"parent":910,"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","ref":"SwitchCaseItemListSyntax","value":{"text":"SwitchCaseItemListSyntax"}},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"type":"other","text":"SwitchCaseLabel","id":911,"range":{"startRow":79,"endRow":79,"startColumn":1,"endColumn":13}},{"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>"},"text":"case","id":912,"range":{"startColumn":1,"endColumn":5,"endRow":79,"startRow":79},"structure":[],"type":"other","parent":911},{"text":"SwitchCaseItemList","structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","range":{"startRow":79,"startColumn":6,"endRow":79,"endColumn":12},"id":913,"parent":911},{"text":"SwitchCaseItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"ExpressionPatternSyntax"},"ref":"ExpressionPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","range":{"startRow":79,"endColumn":12,"startColumn":6,"endRow":79},"id":914,"parent":913},{"text":"ExpressionPattern","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"TupleExprSyntax"},"ref":"TupleExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"pattern","range":{"startColumn":6,"endColumn":12,"endRow":79,"startRow":79},"id":915,"parent":914},{"text":"TupleExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"name":"elements","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenElementsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"type":"expr","range":{"startRow":79,"endRow":79,"startColumn":6,"endColumn":12},"id":916,"parent":915},{"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"text":"(","id":917,"range":{"endRow":79,"startColumn":6,"endColumn":7,"startRow":79},"structure":[],"type":"other","parent":916},{"id":918,"type":"collection","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}],"parent":916,"text":"LabeledExprList","range":{"endRow":79,"startColumn":7,"endColumn":11,"startRow":79}},{"id":919,"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":918,"text":"LabeledExpr","range":{"startRow":79,"startColumn":7,"endColumn":9,"endRow":79}},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("0")","text":"0"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","range":{"startRow":79,"endColumn":8,"startColumn":7,"endRow":79},"parent":919,"id":920,"text":"IntegerLiteralExpr"},{"token":{"leadingTrivia":"","kind":"integerLiteral("0")","trailingTrivia":""},"text":"0","id":921,"range":{"startColumn":7,"endColumn":8,"endRow":79,"startRow":79},"structure":[],"type":"other","parent":920},{"token":{"leadingTrivia":"","kind":"comma","trailingTrivia":"␣<\/span>"},"text":",","id":922,"range":{"startColumn":8,"endColumn":9,"endRow":79,"startRow":79},"structure":[],"type":"other","parent":919},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DiscardAssignmentExprSyntax","name":"expression","value":{"text":"DiscardAssignmentExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","range":{"startColumn":10,"endColumn":11,"endRow":79,"startRow":79},"parent":918,"id":923,"text":"LabeledExpr"},{"structure":[{"name":"unexpectedBeforeWildcard","value":{"text":"nil"}},{"name":"wildcard","value":{"kind":"wildcard","text":"_"}},{"name":"unexpectedAfterWildcard","value":{"text":"nil"}}],"type":"expr","range":{"startRow":79,"startColumn":10,"endRow":79,"endColumn":11},"parent":923,"id":924,"text":"DiscardAssignmentExpr"},{"token":{"kind":"wildcard","trailingTrivia":"","leadingTrivia":""},"text":"_","id":925,"range":{"endColumn":11,"startColumn":10,"endRow":79,"startRow":79},"structure":[],"type":"other","parent":924},{"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"text":")","id":926,"range":{"endColumn":12,"startColumn":11,"endRow":79,"startRow":79},"structure":[],"type":"other","parent":916},{"token":{"kind":"colon","trailingTrivia":"","leadingTrivia":""},"text":":","id":927,"range":{"endColumn":13,"startColumn":12,"endRow":79,"startRow":79},"structure":[],"type":"other","parent":911},{"range":{"endColumn":50,"startColumn":5,"endRow":80,"startRow":80},"parent":910,"id":928,"text":"CodeBlockItemList","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection"},{"range":{"endColumn":50,"startColumn":5,"startRow":80,"endRow":80},"parent":928,"id":929,"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other"},{"range":{"endColumn":50,"startRow":80,"startColumn":5,"endRow":80},"parent":929,"id":930,"text":"FunctionCallExpr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr"},{"id":931,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","parent":930,"type":"expr","range":{"startRow":80,"startColumn":5,"endColumn":10,"endRow":80}},{"token":{"kind":"identifier("print")","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"text":"print","id":932,"range":{"startRow":80,"endRow":80,"startColumn":5,"endColumn":10},"structure":[],"type":"other","parent":931},{"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"text":"(","id":933,"range":{"startRow":80,"startColumn":10,"endRow":80,"endColumn":11},"structure":[],"type":"other","parent":930},{"range":{"startRow":80,"startColumn":11,"endRow":80,"endColumn":49},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","text":"LabeledExprList","id":934,"parent":930},{"range":{"endColumn":49,"startRow":80,"startColumn":11,"endRow":80},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","text":"LabeledExpr","id":935,"parent":934},{"range":{"startColumn":11,"endColumn":49,"startRow":80,"endRow":80},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments","ref":"StringLiteralSegmentListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":936,"parent":935},{"id":937,"type":"other","range":{"startColumn":11,"endRow":80,"endColumn":12,"startRow":80},"structure":[],"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"text":""","parent":936},{"text":"StringLiteralSegmentList","range":{"startColumn":12,"endRow":80,"endColumn":48,"startRow":80},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"id":938,"type":"collection","parent":936},{"text":"StringSegment","range":{"startColumn":12,"endColumn":16,"endRow":80,"startRow":80},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"(0, ","kind":"stringSegment("(0, ")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":939,"type":"other","parent":938},{"id":940,"type":"other","range":{"startRow":80,"startColumn":12,"endRow":80,"endColumn":16},"structure":[],"token":{"kind":"stringSegment("(0, ")","trailingTrivia":"","leadingTrivia":""},"text":"(0,␣<\/span>","parent":939},{"range":{"startRow":80,"endColumn":30,"endRow":80,"startColumn":16},"id":941,"parent":938,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment"},{"id":942,"type":"other","range":{"startRow":80,"startColumn":16,"endColumn":17,"endRow":80},"structure":[],"token":{"kind":"backslash","leadingTrivia":"","trailingTrivia":""},"parent":941,"text":"\\"},{"id":943,"type":"other","range":{"startRow":80,"startColumn":17,"endColumn":18,"endRow":80},"structure":[],"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"parent":941,"text":"("},{"type":"collection","range":{"startRow":80,"startColumn":18,"endColumn":29,"endRow":80},"id":944,"parent":941,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"type":"other","range":{"endColumn":29,"startRow":80,"startColumn":18,"endRow":80},"id":945,"parent":944,"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"id":946,"text":"MemberAccessExpr","parent":945,"range":{"endColumn":29,"startColumn":18,"endRow":80,"startRow":80},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"base","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"type":"expr"},{"id":947,"text":"DeclReferenceExpr","parent":946,"range":{"endRow":80,"startColumn":18,"startRow":80,"endColumn":27},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"somePoint","kind":"identifier("somePoint")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"id":948,"type":"other","range":{"startRow":80,"endColumn":27,"startColumn":18,"endRow":80},"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("somePoint")"},"parent":947,"text":"somePoint"},{"id":949,"type":"other","range":{"startRow":80,"endColumn":28,"startColumn":27,"endRow":80},"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"},"parent":946,"text":"."},{"parent":946,"range":{"startRow":80,"endColumn":29,"startColumn":28,"endRow":80},"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"1","kind":"integerLiteral("1")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":950,"type":"expr"},{"id":951,"type":"other","range":{"endRow":80,"startRow":80,"endColumn":29,"startColumn":28},"structure":[],"token":{"kind":"integerLiteral("1")","leadingTrivia":"","trailingTrivia":""},"parent":950,"text":"1"},{"id":952,"type":"other","range":{"endRow":80,"startRow":80,"endColumn":30,"startColumn":29},"structure":[],"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"parent":941,"text":")"},{"parent":938,"range":{"endRow":80,"startRow":80,"endColumn":48,"startColumn":30},"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(") is on the y-axis")","text":") is on the y-axis"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":953,"type":"other"},{"id":954,"type":"other","range":{"endRow":80,"startRow":80,"startColumn":30,"endColumn":48},"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(") is on the y-axis")"},"parent":953,"text":")␣<\/span>is␣<\/span>on␣<\/span>the␣<\/span>y-axis"},{"id":955,"type":"other","range":{"endColumn":49,"startRow":80,"endRow":80,"startColumn":48},"structure":[],"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"parent":936,"text":"""},{"id":956,"type":"other","range":{"endColumn":50,"startRow":80,"endRow":80,"startColumn":49},"structure":[],"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"parent":930,"text":")"},{"range":{"endColumn":50,"startRow":80,"endRow":80,"startColumn":50},"parent":930,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","id":957,"text":"MultipleTrailingClosureElementList"},{"range":{"startRow":81,"startColumn":1,"endRow":82,"endColumn":64},"parent":827,"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other","id":958,"text":"SwitchCase"},{"range":{"startColumn":1,"startRow":81,"endRow":81,"endColumn":23},"parent":958,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCaseKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndCaseItems"},{"value":{"text":"SwitchCaseItemListSyntax"},"ref":"SwitchCaseItemListSyntax","name":"caseItems"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"type":"other","id":959,"text":"SwitchCaseLabel"},{"id":960,"type":"other","range":{"startRow":81,"startColumn":1,"endRow":81,"endColumn":5},"structure":[],"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)"},"text":"case","parent":959},{"range":{"startRow":81,"startColumn":6,"endRow":81,"endColumn":22},"type":"collection","structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":961,"text":"SwitchCaseItemList","parent":959},{"range":{"startColumn":6,"endRow":81,"startRow":81,"endColumn":22},"type":"other","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":962,"text":"SwitchCaseItem","parent":961},{"range":{"startRow":81,"endRow":81,"endColumn":22,"startColumn":6},"type":"pattern","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"TupleExprSyntax","value":{"text":"TupleExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"id":963,"text":"ExpressionPattern","parent":962},{"id":964,"parent":963,"text":"TupleExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"range":{"startColumn":6,"endRow":81,"endColumn":22,"startRow":81},"type":"expr"},{"id":965,"type":"other","range":{"startColumn":6,"endRow":81,"startRow":81,"endColumn":7},"structure":[],"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"parent":964,"text":"("},{"id":966,"parent":964,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}],"range":{"startColumn":7,"endRow":81,"startRow":81,"endColumn":21},"type":"collection"},{"id":967,"parent":966,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"endRow":81,"startRow":81,"endColumn":14,"startColumn":7},"type":"other"},{"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"PrefixOperatorExprSyntax","name":"leftOperand","value":{"text":"PrefixOperatorExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"BinaryOperatorExprSyntax","name":"operator","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"rightOperand","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","text":"InfixOperatorExpr","parent":967,"id":968,"range":{"startColumn":7,"endColumn":13,"startRow":81,"endRow":81}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"text":"-","kind":"prefixOperator("-")"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"expr","text":"PrefixOperatorExpr","parent":968,"id":969,"range":{"startColumn":7,"endColumn":9,"endRow":81,"startRow":81}},{"id":970,"type":"other","range":{"endRow":81,"endColumn":8,"startColumn":7,"startRow":81},"structure":[],"token":{"trailingTrivia":"","kind":"prefixOperator("-")","leadingTrivia":""},"text":"-","parent":969},{"text":"IntegerLiteralExpr","type":"expr","id":971,"range":{"endRow":81,"endColumn":9,"startColumn":8,"startRow":81},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"2","kind":"integerLiteral("2")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":969},{"id":972,"type":"other","range":{"endRow":81,"endColumn":9,"startRow":81,"startColumn":8},"structure":[],"token":{"leadingTrivia":"","kind":"integerLiteral("2")","trailingTrivia":""},"text":"2","parent":971},{"text":"BinaryOperatorExpr","type":"expr","id":973,"range":{"endRow":81,"endColumn":12,"startRow":81,"startColumn":9},"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("...")","text":"..."}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"parent":968},{"id":974,"type":"other","range":{"endColumn":12,"startRow":81,"startColumn":9,"endRow":81},"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"binaryOperator("...")"},"text":"...","parent":973},{"text":"IntegerLiteralExpr","type":"expr","id":975,"range":{"endColumn":13,"startRow":81,"startColumn":12,"endRow":81},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"2","kind":"integerLiteral("2")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"parent":968},{"id":976,"type":"other","range":{"endColumn":13,"startColumn":12,"startRow":81,"endRow":81},"structure":[],"token":{"kind":"integerLiteral("2")","trailingTrivia":"","leadingTrivia":""},"text":"2","parent":975},{"id":977,"type":"other","range":{"startColumn":13,"startRow":81,"endColumn":14,"endRow":81},"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"parent":967,"text":","},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"InfixOperatorExprSyntax","name":"expression","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"startColumn":15,"startRow":81,"endColumn":21,"endRow":81},"type":"other","id":978,"parent":966,"text":"LabeledExpr"},{"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"PrefixOperatorExprSyntax","value":{"text":"PrefixOperatorExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"range":{"startColumn":15,"endColumn":21,"startRow":81,"endRow":81},"type":"expr","id":979,"parent":978,"text":"InfixOperatorExpr"},{"text":"PrefixOperatorExpr","range":{"startColumn":15,"startRow":81,"endRow":81,"endColumn":17},"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"-","kind":"prefixOperator("-")"}},{"name":"unexpectedBetweenOperatorAndExpression","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"expression","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"expr","parent":979,"id":980},{"id":981,"type":"other","range":{"startRow":81,"endRow":81,"endColumn":16,"startColumn":15},"structure":[],"token":{"kind":"prefixOperator("-")","leadingTrivia":"","trailingTrivia":""},"text":"-","parent":980},{"text":"IntegerLiteralExpr","range":{"startRow":81,"endRow":81,"endColumn":17,"startColumn":16},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"2","kind":"integerLiteral("2")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","parent":980,"id":982},{"id":983,"type":"other","range":{"startColumn":16,"startRow":81,"endRow":81,"endColumn":17},"structure":[],"token":{"kind":"integerLiteral("2")","leadingTrivia":"","trailingTrivia":""},"text":"2","parent":982},{"text":"BinaryOperatorExpr","range":{"startColumn":17,"startRow":81,"endRow":81,"endColumn":20},"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("...")","text":"..."}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","parent":979,"id":984},{"id":985,"type":"other","range":{"startRow":81,"endColumn":20,"startColumn":17,"endRow":81},"structure":[],"token":{"trailingTrivia":"","kind":"binaryOperator("...")","leadingTrivia":""},"text":"...","parent":984},{"range":{"startRow":81,"endRow":81,"startColumn":20,"endColumn":21},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"2","kind":"integerLiteral("2")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":986,"text":"IntegerLiteralExpr","type":"expr","parent":979},{"structure":[],"type":"other","parent":986,"text":"2","range":{"endColumn":21,"startColumn":20,"endRow":81,"startRow":81},"token":{"kind":"integerLiteral("2")","leadingTrivia":"","trailingTrivia":""},"id":987},{"structure":[],"type":"other","parent":964,"text":")","range":{"endColumn":22,"startColumn":21,"endRow":81,"startRow":81},"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"id":988},{"structure":[],"type":"other","parent":959,"text":":","range":{"endColumn":23,"startColumn":22,"endRow":81,"startRow":81},"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":""},"id":989},{"range":{"endColumn":64,"startColumn":5,"endRow":82,"startRow":82},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":990,"text":"CodeBlockItemList","type":"collection","parent":958},{"range":{"startRow":82,"endRow":82,"startColumn":5,"endColumn":64},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":991,"text":"CodeBlockItem","type":"other","parent":990},{"range":{"startColumn":5,"endColumn":64,"startRow":82,"endRow":82},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":992,"text":"FunctionCallExpr","type":"expr","parent":991},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":992,"range":{"startColumn":5,"startRow":82,"endRow":82,"endColumn":10},"type":"expr","id":993,"text":"DeclReferenceExpr"},{"structure":[],"type":"other","parent":993,"text":"print","range":{"endColumn":10,"startRow":82,"endRow":82,"startColumn":5},"token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")"},"id":994},{"structure":[],"type":"other","parent":992,"text":"(","range":{"endRow":82,"endColumn":11,"startRow":82,"startColumn":10},"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"id":995},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":996,"text":"LabeledExprList","range":{"endRow":82,"endColumn":63,"startRow":82,"startColumn":11},"parent":992},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":997,"text":"LabeledExpr","range":{"endRow":82,"endColumn":63,"startRow":82,"startColumn":11},"parent":996},{"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"type":"expr","id":998,"text":"StringLiteralExpr","range":{"startRow":82,"startColumn":11,"endRow":82,"endColumn":63},"parent":997},{"structure":[],"type":"other","parent":998,"text":""","range":{"startRow":82,"startColumn":11,"endColumn":12,"endRow":82},"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"id":999},{"id":1000,"parent":998,"range":{"startRow":82,"startColumn":12,"endColumn":62,"endRow":82},"text":"StringLiteralSegmentList","type":"collection","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"5"}}]},{"id":1001,"parent":1000,"range":{"endColumn":13,"startRow":82,"startColumn":12,"endRow":82},"text":"StringSegment","type":"other","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"(","kind":"stringSegment("(")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"structure":[],"type":"other","parent":1001,"text":"(","range":{"endColumn":13,"startRow":82,"endRow":82,"startColumn":12},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("(")"},"id":1002},{"id":1003,"parent":1000,"range":{"startColumn":13,"startRow":82,"endColumn":27,"endRow":82},"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"type":"other","text":"ExpressionSegment"},{"structure":[],"type":"other","parent":1003,"text":"\\","range":{"endColumn":14,"endRow":82,"startRow":82,"startColumn":13},"token":{"leadingTrivia":"","kind":"backslash","trailingTrivia":""},"id":1004},{"structure":[],"type":"other","parent":1003,"text":"(","range":{"endColumn":15,"endRow":82,"startRow":82,"startColumn":14},"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"id":1005},{"id":1006,"parent":1003,"range":{"endColumn":26,"endRow":82,"startRow":82,"startColumn":15},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList"},{"id":1007,"parent":1006,"range":{"endColumn":26,"endRow":82,"startRow":82,"startColumn":15},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"MemberAccessExprSyntax"},"name":"expression","ref":"MemberAccessExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr"},{"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"id":1008,"text":"MemberAccessExpr","range":{"endColumn":26,"startRow":82,"endRow":82,"startColumn":15},"parent":1007,"type":"expr"},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("somePoint")","text":"somePoint"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1009,"text":"DeclReferenceExpr","range":{"startColumn":15,"endColumn":24,"startRow":82,"endRow":82},"parent":1008,"type":"expr"},{"structure":[],"type":"other","parent":1009,"text":"somePoint","range":{"startRow":82,"startColumn":15,"endRow":82,"endColumn":24},"token":{"kind":"identifier("somePoint")","trailingTrivia":"","leadingTrivia":""},"id":1010},{"structure":[],"type":"other","parent":1008,"text":".","range":{"startRow":82,"startColumn":24,"endRow":82,"endColumn":25},"token":{"kind":"period","trailingTrivia":"","leadingTrivia":""},"id":1011},{"parent":1008,"text":"DeclReferenceExpr","range":{"startRow":82,"startColumn":25,"endRow":82,"endColumn":26},"id":1012,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"integerLiteral("0")","text":"0"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"structure":[],"type":"other","parent":1012,"text":"0","range":{"startColumn":25,"endRow":82,"endColumn":26,"startRow":82},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("0")"},"id":1013},{"structure":[],"type":"other","parent":1003,"text":")","range":{"startColumn":26,"endRow":82,"endColumn":27,"startRow":82},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"id":1014},{"parent":1000,"text":"StringSegment","range":{"startColumn":27,"endRow":82,"endColumn":29,"startRow":82},"id":1015,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":", ","kind":"stringSegment(", ")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other"},{"structure":[],"type":"other","parent":1015,"text":",␣<\/span>","range":{"startColumn":27,"endColumn":29,"startRow":82,"endRow":82},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment(", ")"},"id":1016},{"range":{"startColumn":29,"endColumn":43,"startRow":82,"endRow":82},"parent":1000,"id":1017,"text":"ExpressionSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other"},{"structure":[],"type":"other","parent":1017,"text":"\\","range":{"endColumn":30,"startRow":82,"startColumn":29,"endRow":82},"token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"id":1018},{"structure":[],"type":"other","parent":1017,"text":"(","range":{"endColumn":31,"startRow":82,"startColumn":30,"endRow":82},"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"id":1019},{"range":{"endColumn":42,"startRow":82,"startColumn":31,"endRow":82},"parent":1017,"id":1020,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"parent":1020,"text":"LabeledExpr","range":{"endRow":82,"startColumn":31,"endColumn":42,"startRow":82},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":1021,"type":"other"},{"parent":1021,"text":"MemberAccessExpr","range":{"startColumn":31,"endColumn":42,"startRow":82,"endRow":82},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"id":1022,"type":"expr"},{"id":1023,"text":"DeclReferenceExpr","range":{"startRow":82,"endRow":82,"endColumn":40,"startColumn":31},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"somePoint","kind":"identifier("somePoint")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","parent":1022},{"structure":[],"type":"other","parent":1023,"text":"somePoint","range":{"endColumn":40,"startColumn":31,"endRow":82,"startRow":82},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("somePoint")"},"id":1024},{"structure":[],"type":"other","parent":1022,"text":".","range":{"endColumn":41,"startColumn":40,"endRow":82,"startRow":82},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"},"id":1025},{"id":1026,"text":"DeclReferenceExpr","range":{"endColumn":42,"startColumn":41,"endRow":82,"startRow":82},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"1","kind":"integerLiteral("1")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","parent":1022},{"structure":[],"type":"other","parent":1026,"text":"1","range":{"startRow":82,"endRow":82,"endColumn":42,"startColumn":41},"token":{"kind":"integerLiteral("1")","trailingTrivia":"","leadingTrivia":""},"id":1027},{"structure":[],"type":"other","parent":1017,"text":")","range":{"startRow":82,"endRow":82,"endColumn":43,"startColumn":42},"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"id":1028},{"range":{"startColumn":43,"endColumn":62,"endRow":82,"startRow":82},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":") is inside the box","kind":"stringSegment(") is inside the box")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","parent":1000,"id":1029,"text":"StringSegment"},{"structure":[],"type":"other","parent":1029,"text":")␣<\/span>is␣<\/span>inside␣<\/span>the␣<\/span>box","range":{"endRow":82,"endColumn":62,"startRow":82,"startColumn":43},"token":{"kind":"stringSegment(") is inside the box")","trailingTrivia":"","leadingTrivia":""},"id":1030},{"structure":[],"id":1031,"range":{"endRow":82,"endColumn":63,"startRow":82,"startColumn":62},"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"type":"other","text":""","parent":998},{"structure":[],"id":1032,"range":{"endRow":82,"endColumn":64,"startRow":82,"startColumn":63},"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"type":"other","text":")","parent":992},{"type":"collection","id":1033,"parent":992,"range":{"endRow":82,"endColumn":64,"startRow":82,"startColumn":64},"text":"MultipleTrailingClosureElementList","structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"type":"other","id":1034,"parent":827,"range":{"endRow":84,"startRow":83,"endColumn":68,"startColumn":1},"text":"SwitchCase","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeAndLabel"},{"value":{"text":"SwitchDefaultLabelSyntax"},"name":"label","ref":"SwitchDefaultLabelSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterStatements"}]},{"type":"other","id":1035,"parent":1034,"range":{"startColumn":1,"endColumn":9,"startRow":83,"endRow":83},"text":"SwitchDefaultLabel","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDefaultKeyword"},{"name":"defaultKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.default)","text":"default"}},{"name":"unexpectedBetweenDefaultKeywordAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}]},{"structure":[],"id":1036,"range":{"endColumn":8,"startColumn":1,"endRow":83,"startRow":83},"token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.default)"},"type":"other","text":"default","parent":1035},{"structure":[],"id":1037,"range":{"endColumn":9,"startColumn":8,"endRow":83,"startRow":83},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"colon"},"type":"other","text":":","parent":1035},{"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"range":{"endColumn":68,"startColumn":5,"endRow":84,"startRow":84},"type":"collection","text":"CodeBlockItemList","parent":1034,"id":1038},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"name":"item","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"range":{"startColumn":5,"startRow":84,"endRow":84,"endColumn":68},"type":"other","text":"CodeBlockItem","parent":1038,"id":1039},{"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"range":{"startRow":84,"startColumn":5,"endRow":84,"endColumn":68},"type":"expr","text":"FunctionCallExpr","parent":1039,"id":1040},{"range":{"startColumn":5,"endColumn":10,"startRow":84,"endRow":84},"parent":1040,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1041,"text":"DeclReferenceExpr","type":"expr"},{"structure":[],"id":1042,"range":{"startColumn":5,"endColumn":10,"endRow":84,"startRow":84},"token":{"kind":"identifier("print")","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"type":"other","text":"print","parent":1041},{"structure":[],"id":1043,"range":{"endColumn":11,"endRow":84,"startRow":84,"startColumn":10},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"type":"other","text":"(","parent":1040},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","range":{"endColumn":67,"endRow":84,"startRow":84,"startColumn":11},"id":1044,"parent":1040,"text":"LabeledExprList"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"expression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","range":{"endRow":84,"endColumn":67,"startRow":84,"startColumn":11},"id":1045,"parent":1044,"text":"LabeledExpr"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments","ref":"StringLiteralSegmentListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","range":{"startColumn":11,"endRow":84,"endColumn":67,"startRow":84},"id":1046,"parent":1045,"text":"StringLiteralExpr"},{"structure":[],"id":1047,"range":{"startRow":84,"startColumn":11,"endRow":84,"endColumn":12},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"type":"other","text":""","parent":1046},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}],"type":"collection","range":{"startRow":84,"startColumn":12,"endRow":84,"endColumn":66},"parent":1046,"text":"StringLiteralSegmentList","id":1048},{"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"(","kind":"stringSegment("(")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","range":{"endColumn":13,"startRow":84,"startColumn":12,"endRow":84},"parent":1048,"text":"StringSegment","id":1049},{"structure":[],"id":1050,"range":{"startColumn":12,"endColumn":13,"endRow":84,"startRow":84},"token":{"kind":"stringSegment("(")","trailingTrivia":"","leadingTrivia":""},"type":"other","text":"(","parent":1049},{"text":"ExpressionSegment","type":"other","parent":1048,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":1051,"range":{"startRow":84,"endRow":84,"startColumn":13,"endColumn":27}},{"structure":[],"id":1052,"range":{"endColumn":14,"startRow":84,"startColumn":13,"endRow":84},"token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"type":"other","text":"\\","parent":1051},{"structure":[],"id":1053,"range":{"endColumn":15,"startRow":84,"startColumn":14,"endRow":84},"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"type":"other","text":"(","parent":1051},{"text":"LabeledExprList","type":"collection","parent":1051,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":1054,"range":{"endColumn":26,"startRow":84,"startColumn":15,"endRow":84}},{"text":"LabeledExpr","type":"other","parent":1054,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":1055,"range":{"startColumn":15,"startRow":84,"endRow":84,"endColumn":26}},{"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"text":"MemberAccessExpr","parent":1055,"id":1056,"range":{"startRow":84,"startColumn":15,"endColumn":26,"endRow":84},"type":"expr"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"name":"baseName","value":{"kind":"identifier("somePoint")","text":"somePoint"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","parent":1056,"id":1057,"range":{"endRow":84,"startRow":84,"endColumn":24,"startColumn":15},"type":"expr"},{"structure":[],"id":1058,"range":{"endColumn":24,"endRow":84,"startRow":84,"startColumn":15},"token":{"kind":"identifier("somePoint")","leadingTrivia":"","trailingTrivia":""},"type":"other","text":"somePoint","parent":1057},{"structure":[],"id":1059,"range":{"endColumn":25,"endRow":84,"startRow":84,"startColumn":24},"token":{"kind":"period","leadingTrivia":"","trailingTrivia":""},"type":"other","text":".","parent":1056},{"text":"DeclReferenceExpr","range":{"endColumn":26,"endRow":84,"startRow":84,"startColumn":25},"id":1060,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","parent":1056},{"structure":[],"id":1061,"range":{"endRow":84,"endColumn":26,"startRow":84,"startColumn":25},"token":{"kind":"integerLiteral("0")","leadingTrivia":"","trailingTrivia":""},"type":"other","text":"0","parent":1060},{"structure":[],"id":1062,"range":{"endRow":84,"endColumn":27,"startRow":84,"startColumn":26},"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"type":"other","text":")","parent":1051},{"text":"StringSegment","range":{"endRow":84,"endColumn":29,"startRow":84,"startColumn":27},"id":1063,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(", ")","text":", "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","parent":1048},{"structure":[],"id":1064,"range":{"endColumn":29,"startRow":84,"startColumn":27,"endRow":84},"token":{"kind":"stringSegment(", ")","leadingTrivia":"","trailingTrivia":""},"type":"other","text":",␣<\/span>","parent":1063},{"text":"ExpressionSegment","range":{"endColumn":43,"startRow":84,"startColumn":29,"endRow":84},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"name":"expressions","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":1065,"parent":1048},{"structure":[],"id":1066,"range":{"startColumn":29,"startRow":84,"endRow":84,"endColumn":30},"token":{"leadingTrivia":"","kind":"backslash","trailingTrivia":""},"type":"other","text":"\\","parent":1065},{"structure":[],"id":1067,"range":{"startColumn":30,"startRow":84,"endRow":84,"endColumn":31},"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"type":"other","text":"(","parent":1065},{"text":"LabeledExprList","range":{"startColumn":31,"startRow":84,"endRow":84,"endColumn":42},"type":"collection","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":1068,"parent":1065},{"range":{"endColumn":42,"startRow":84,"endRow":84,"startColumn":31},"type":"other","id":1069,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1068,"text":"LabeledExpr"},{"range":{"startRow":84,"endRow":84,"startColumn":31,"endColumn":42},"type":"expr","id":1070,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"parent":1069,"text":"MemberAccessExpr"},{"text":"DeclReferenceExpr","id":1071,"parent":1070,"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("somePoint")","text":"somePoint"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"startColumn":31,"endColumn":40,"startRow":84,"endRow":84}},{"structure":[],"id":1072,"range":{"startRow":84,"endColumn":40,"endRow":84,"startColumn":31},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("somePoint")"},"type":"other","text":"somePoint","parent":1071},{"structure":[],"id":1073,"range":{"startRow":84,"endColumn":41,"endRow":84,"startColumn":40},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"period"},"type":"other","text":".","parent":1070},{"text":"DeclReferenceExpr","id":1074,"parent":1070,"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"integerLiteral("1")","text":"1"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"range":{"startRow":84,"endColumn":42,"endRow":84,"startColumn":41}},{"structure":[],"id":1075,"range":{"startRow":84,"endRow":84,"startColumn":41,"endColumn":42},"token":{"kind":"integerLiteral("1")","leadingTrivia":"","trailingTrivia":""},"type":"other","text":"1","parent":1074},{"structure":[],"id":1076,"range":{"startRow":84,"endRow":84,"startColumn":42,"endColumn":43},"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"type":"other","text":")","parent":1065},{"parent":1048,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(") is outside of the box")","text":") is outside of the box"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"range":{"startColumn":43,"startRow":84,"endRow":84,"endColumn":66},"id":1077,"type":"other","text":"StringSegment"},{"structure":[],"parent":1077,"type":"other","token":{"leadingTrivia":"","kind":"stringSegment(") is outside of the box")","trailingTrivia":""},"range":{"endRow":84,"startRow":84,"startColumn":43,"endColumn":66},"id":1078,"text":")␣<\/span>is␣<\/span>outside␣<\/span>of␣<\/span>the␣<\/span>box"},{"structure":[],"parent":1046,"type":"other","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"range":{"endRow":84,"startRow":84,"startColumn":66,"endColumn":67},"id":1079,"text":"""},{"structure":[],"parent":1040,"type":"other","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"range":{"endRow":84,"startRow":84,"startColumn":67,"endColumn":68},"id":1080,"text":")"},{"parent":1040,"range":{"endRow":84,"startRow":84,"startColumn":68,"endColumn":68},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"MultipleTrailingClosureElementList","type":"collection","id":1081},{"structure":[],"parent":822,"type":"other","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"startRow":85,"endColumn":2,"startColumn":1,"endRow":85},"id":1082,"text":"}"},{"parent":1,"range":{"startRow":88,"endColumn":26,"startColumn":1,"endRow":88},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"VariableDeclSyntax","name":"item","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","type":"other","id":1083},{"parent":1083,"range":{"startRow":88,"endRow":88,"startColumn":1,"endColumn":26},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"text":"VariableDecl","type":"decl","id":1084},{"id":1085,"parent":1084,"text":"AttributeList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","range":{"endColumn":2,"startColumn":2,"endRow":85,"startRow":85}},{"id":1086,"parent":1084,"text":"DeclModifierList","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","range":{"startRow":85,"endColumn":2,"endRow":85,"startColumn":2}},{"structure":[],"parent":1084,"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>Switch␣<\/span>with␣<\/span>value␣<\/span>binding<\/span>↲<\/span>"},"range":{"endRow":88,"startColumn":1,"startRow":88,"endColumn":4},"id":1087,"text":"let"},{"id":1088,"parent":1084,"text":"PatternBindingList","structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","range":{"endRow":88,"startColumn":5,"startRow":88,"endColumn":26}},{"id":1089,"parent":1088,"text":"PatternBinding","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","range":{"endColumn":26,"endRow":88,"startRow":88,"startColumn":5}},{"range":{"endRow":88,"endColumn":17,"startColumn":5,"startRow":88},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("anotherPoint")","text":"anotherPoint"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":1090,"type":"pattern","text":"IdentifierPattern","parent":1089},{"structure":[],"type":"other","parent":1090,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("anotherPoint")"},"range":{"startRow":88,"startColumn":5,"endColumn":17,"endRow":88},"id":1091,"text":"anotherPoint"},{"range":{"startRow":88,"startColumn":18,"endColumn":26,"endRow":88},"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"TupleExprSyntax","name":"value","value":{"text":"TupleExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":1092,"type":"other","text":"InitializerClause","parent":1089},{"structure":[],"type":"other","parent":1092,"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"range":{"endColumn":19,"endRow":88,"startRow":88,"startColumn":18},"id":1093,"text":"="},{"type":"expr","id":1094,"parent":1092,"text":"TupleExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"range":{"endColumn":26,"endRow":88,"startRow":88,"startColumn":20}},{"structure":[],"type":"other","parent":1094,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"startColumn":20,"startRow":88,"endRow":88,"endColumn":21},"id":1095,"text":"("},{"type":"collection","id":1096,"parent":1094,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}],"range":{"startColumn":21,"startRow":88,"endRow":88,"endColumn":25}},{"type":"other","id":1097,"parent":1096,"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"startColumn":21,"startRow":88,"endRow":88,"endColumn":23}},{"parent":1097,"text":"IntegerLiteralExpr","id":1098,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("2")","text":"2"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"startRow":88,"endRow":88,"endColumn":22,"startColumn":21},"type":"expr"},{"structure":[],"parent":1098,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("2")"},"range":{"endColumn":22,"endRow":88,"startRow":88,"startColumn":21},"id":1099,"text":"2"},{"structure":[],"parent":1097,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"range":{"endColumn":23,"endRow":88,"startRow":88,"startColumn":22},"id":1100,"text":","},{"parent":1096,"text":"LabeledExpr","id":1101,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endColumn":25,"endRow":88,"startRow":88,"startColumn":24},"type":"other"},{"id":1102,"parent":1101,"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"startColumn":24,"startRow":88,"endColumn":25,"endRow":88},"type":"expr"},{"structure":[],"parent":1102,"type":"other","token":{"kind":"integerLiteral("0")","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":88,"startColumn":24,"endColumn":25,"endRow":88},"id":1103,"text":"0"},{"structure":[],"parent":1094,"type":"other","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":88,"startColumn":25,"endColumn":26,"endRow":88},"id":1104,"text":")"},{"id":1105,"parent":1,"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ExpressionStmtSyntax"},"ref":"ExpressionStmtSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"range":{"startRow":89,"startColumn":1,"endColumn":2,"endRow":96},"type":"other"},{"id":1106,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"SwitchExprSyntax","value":{"text":"SwitchExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"parent":1105,"range":{"startRow":89,"startColumn":1,"endRow":96,"endColumn":2},"text":"ExpressionStmt","type":"other"},{"id":1107,"structure":[{"name":"unexpectedBeforeSwitchKeyword","value":{"text":"nil"}},{"name":"switchKeyword","value":{"text":"switch","kind":"keyword(SwiftSyntax.Keyword.switch)"}},{"name":"unexpectedBetweenSwitchKeywordAndSubject","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"subject","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenSubjectAndLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndCases","value":{"text":"nil"}},{"ref":"SwitchCaseListSyntax","name":"cases","value":{"text":"SwitchCaseListSyntax"}},{"name":"unexpectedBetweenCasesAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"parent":1106,"range":{"startRow":89,"startColumn":1,"endRow":96,"endColumn":2},"text":"SwitchExpr","type":"expr"},{"structure":[],"parent":1107,"type":"other","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.switch)"},"range":{"startColumn":1,"startRow":89,"endRow":89,"endColumn":7},"id":1108,"text":"switch"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"anotherPoint","kind":"identifier("anotherPoint")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"range":{"startRow":89,"endRow":89,"endColumn":20,"startColumn":8},"id":1109,"type":"expr","text":"DeclReferenceExpr","parent":1107},{"structure":[],"type":"other","parent":1109,"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("anotherPoint")","leadingTrivia":""},"range":{"endColumn":20,"endRow":89,"startRow":89,"startColumn":8},"id":1110,"text":"anotherPoint"},{"structure":[],"type":"other","parent":1107,"token":{"trailingTrivia":"","kind":"leftBrace","leadingTrivia":""},"range":{"endColumn":22,"endRow":89,"startRow":89,"startColumn":21},"id":1111,"text":"{"},{"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"range":{"endColumn":44,"endRow":95,"startRow":90,"startColumn":1},"id":1112,"type":"collection","text":"SwitchCaseList","parent":1107},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeAndLabel"},{"value":{"text":"SwitchCaseLabelSyntax"},"ref":"SwitchCaseLabelSyntax","name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"range":{"startColumn":1,"startRow":90,"endRow":91,"endColumn":51},"id":1113,"type":"other","text":"SwitchCase","parent":1112},{"parent":1113,"text":"SwitchCaseLabel","id":1114,"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"text":"case","kind":"keyword(SwiftSyntax.Keyword.case)"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","value":{"text":"SwitchCaseItemListSyntax"},"ref":"SwitchCaseItemListSyntax"},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"range":{"startRow":90,"endColumn":17,"endRow":90,"startColumn":1},"type":"other"},{"structure":[],"parent":1114,"type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)"},"range":{"endColumn":5,"endRow":90,"startRow":90,"startColumn":1},"id":1115,"text":"case"},{"parent":1114,"text":"SwitchCaseItemList","id":1116,"structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"range":{"endColumn":16,"endRow":90,"startRow":90,"startColumn":6},"type":"collection"},{"parent":1116,"text":"SwitchCaseItem","id":1117,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"startRow":90,"endColumn":16,"endRow":90,"startColumn":6},"type":"other"},{"text":"ExpressionPattern","range":{"endColumn":16,"startRow":90,"startColumn":6,"endRow":90},"type":"pattern","id":1118,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"TupleExprSyntax"},"name":"expression","ref":"TupleExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"parent":1117},{"text":"TupleExpr","range":{"startColumn":6,"endRow":90,"endColumn":16,"startRow":90},"type":"expr","id":1119,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenElementsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":1118},{"structure":[],"type":"other","parent":1119,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endColumn":7,"startRow":90,"startColumn":6,"endRow":90},"id":1120,"text":"("},{"type":"collection","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"name":"Count","value":{"text":"2"}}],"parent":1119,"text":"LabeledExprList","range":{"endRow":90,"startRow":90,"startColumn":7,"endColumn":15},"id":1121},{"type":"other","range":{"startColumn":7,"endColumn":13,"startRow":90,"endRow":90},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"PatternExprSyntax"},"name":"expression","ref":"PatternExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":1121,"id":1122,"text":"LabeledExpr"},{"type":"expr","range":{"startColumn":7,"endColumn":12,"endRow":90,"startRow":90},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"ValueBindingPatternSyntax"},"ref":"ValueBindingPatternSyntax"},{"name":"unexpectedAfterPattern","value":{"text":"nil"}}],"parent":1122,"id":1123,"text":"PatternExpr"},{"type":"pattern","range":{"startRow":90,"startColumn":7,"endRow":90,"endColumn":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndPattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterPattern"}],"parent":1123,"id":1124,"text":"ValueBindingPattern"},{"structure":[],"parent":1124,"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endRow":90,"endColumn":10,"startRow":90,"startColumn":7},"id":1125,"text":"let"},{"parent":1124,"text":"IdentifierPattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("x")","text":"x"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","id":1126,"range":{"endRow":90,"endColumn":12,"startRow":90,"startColumn":11}},{"structure":[],"parent":1126,"type":"other","token":{"trailingTrivia":"","kind":"identifier("x")","leadingTrivia":""},"range":{"endRow":90,"startColumn":11,"startRow":90,"endColumn":12},"id":1127,"text":"x"},{"structure":[],"parent":1122,"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"comma","leadingTrivia":""},"range":{"endRow":90,"startColumn":12,"startRow":90,"endColumn":13},"id":1128,"text":","},{"parent":1121,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":1129,"range":{"endRow":90,"startColumn":14,"startRow":90,"endColumn":15}},{"text":"IntegerLiteralExpr","type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"0","kind":"integerLiteral("0")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"range":{"endRow":90,"startColumn":14,"startRow":90,"endColumn":15},"parent":1129,"id":1130},{"structure":[],"type":"other","parent":1130,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("0")"},"range":{"startColumn":14,"endColumn":15,"endRow":90,"startRow":90},"id":1131,"text":"0"},{"text":")","structure":[],"parent":1119,"id":1132,"range":{"startColumn":15,"endColumn":16,"endRow":90,"startRow":90},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"type":"other"},{"text":":","structure":[],"parent":1114,"id":1133,"range":{"startColumn":16,"endColumn":17,"endRow":90,"startRow":90},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"colon"},"type":"other"},{"text":"CodeBlockItemList","type":"collection","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"startColumn":5,"endColumn":51,"endRow":91,"startRow":91},"parent":1113,"id":1134},{"text":"CodeBlockItem","type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"range":{"startRow":91,"endRow":91,"endColumn":51,"startColumn":5},"parent":1134,"id":1135},{"parent":1135,"text":"FunctionCallExpr","range":{"endColumn":51,"startRow":91,"startColumn":5,"endRow":91},"id":1136,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr"},{"parent":1136,"text":"DeclReferenceExpr","range":{"endColumn":10,"endRow":91,"startRow":91,"startColumn":5},"id":1137,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"text":"print","structure":[],"parent":1137,"id":1138,"range":{"endRow":91,"endColumn":10,"startRow":91,"startColumn":5},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")","trailingTrivia":""},"type":"other"},{"text":"(","structure":[],"parent":1136,"id":1139,"range":{"endRow":91,"endColumn":11,"startRow":91,"startColumn":10},"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"type":"other"},{"range":{"endRow":91,"endColumn":50,"startRow":91,"startColumn":11},"id":1140,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"LabeledExprList","parent":1136,"type":"collection"},{"range":{"startColumn":11,"startRow":91,"endColumn":50,"endRow":91},"id":1141,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"LabeledExpr","parent":1140,"type":"other"},{"range":{"startRow":91,"endColumn":50,"endRow":91,"startColumn":11},"id":1142,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"text":"StringLiteralExpr","parent":1141,"type":"expr"},{"text":""","parent":1142,"structure":[],"id":1143,"range":{"startRow":91,"startColumn":11,"endRow":91,"endColumn":12},"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"range":{"startRow":91,"startColumn":12,"endRow":91,"endColumn":49},"text":"StringLiteralSegmentList","id":1144,"type":"collection","parent":1142,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}]},{"range":{"startColumn":12,"endColumn":45,"endRow":91,"startRow":91},"text":"StringSegment","id":1145,"type":"other","parent":1144,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("on the x-axis with an x value of ")","text":"on the x-axis with an x value of "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"text":"on␣<\/span>the␣<\/span>x-axis␣<\/span>with␣<\/span>an␣<\/span>x␣<\/span>value␣<\/span>of␣<\/span>","structure":[],"parent":1145,"id":1146,"range":{"endRow":91,"startRow":91,"endColumn":45,"startColumn":12},"token":{"kind":"stringSegment("on the x-axis with an x value of ")","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"range":{"endRow":91,"startRow":91,"endColumn":49,"startColumn":45},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"name":"expressions","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","id":1147,"parent":1144,"text":"ExpressionSegment"},{"text":"\\","structure":[],"parent":1147,"id":1148,"range":{"startRow":91,"startColumn":45,"endRow":91,"endColumn":46},"token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"type":"other"},{"text":"(","structure":[],"parent":1147,"id":1149,"range":{"startRow":91,"startColumn":46,"endRow":91,"endColumn":47},"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"type":"other"},{"parent":1147,"text":"LabeledExprList","id":1150,"range":{"startColumn":47,"startRow":91,"endRow":91,"endColumn":48},"type":"collection","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"name":"Count","value":{"text":"1"}}]},{"id":1151,"parent":1150,"text":"LabeledExpr","range":{"endColumn":48,"endRow":91,"startColumn":47,"startRow":91},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"id":1152,"parent":1151,"text":"DeclReferenceExpr","range":{"startRow":91,"endRow":91,"startColumn":47,"endColumn":48},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"x","kind":"identifier("x")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"text":"x","parent":1152,"structure":[],"id":1153,"range":{"endColumn":48,"startRow":91,"endRow":91,"startColumn":47},"token":{"kind":"identifier("x")","leadingTrivia":"","trailingTrivia":""},"type":"other"},{"text":")","parent":1147,"structure":[],"id":1154,"range":{"startRow":91,"endRow":91,"startColumn":48,"endColumn":49},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"type":"other"},{"type":"other","id":1155,"text":"StringSegment","parent":1144,"range":{"startRow":91,"endRow":91,"startColumn":49,"endColumn":49},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("")","text":""}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"text":"","parent":1155,"structure":[],"id":1156,"range":{"endRow":91,"startRow":91,"endColumn":49,"startColumn":49},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("")"},"type":"other"},{"text":""","parent":1142,"structure":[],"id":1157,"range":{"endRow":91,"startRow":91,"endColumn":50,"startColumn":49},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"type":"other"},{"text":")","parent":1136,"structure":[],"id":1158,"range":{"endRow":91,"startRow":91,"endColumn":51,"startColumn":50},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"type":"other"},{"type":"collection","id":1159,"text":"MultipleTrailingClosureElementList","parent":1136,"range":{"endRow":91,"startRow":91,"endColumn":51,"startColumn":51},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"type":"other","id":1160,"text":"SwitchCase","parent":1112,"range":{"startColumn":1,"startRow":92,"endRow":93,"endColumn":50},"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"SwitchCaseLabelSyntax"},"ref":"SwitchCaseLabelSyntax"},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}]},{"parent":1160,"range":{"startColumn":1,"endColumn":17,"startRow":92,"endRow":92},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCaseKeyword"},{"value":{"text":"case","kind":"keyword(SwiftSyntax.Keyword.case)"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndCaseItems"},{"value":{"text":"SwitchCaseItemListSyntax"},"name":"caseItems","ref":"SwitchCaseItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"id":1161,"type":"other","text":"SwitchCaseLabel"},{"text":"case","parent":1161,"structure":[],"id":1162,"range":{"endRow":92,"endColumn":5,"startRow":92,"startColumn":1},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)"},"type":"other"},{"parent":1161,"range":{"endRow":92,"endColumn":16,"startRow":92,"startColumn":6},"structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":1163,"type":"collection","text":"SwitchCaseItemList"},{"parent":1163,"range":{"endRow":92,"startColumn":6,"endColumn":16,"startRow":92},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":1164,"type":"other","text":"SwitchCaseItem"},{"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"ref":"TupleExprSyntax","name":"expression","value":{"text":"TupleExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"id":1165,"parent":1164,"text":"ExpressionPattern","range":{"endRow":92,"startColumn":6,"endColumn":16,"startRow":92},"type":"pattern"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":1166,"parent":1165,"text":"TupleExpr","range":{"endColumn":16,"endRow":92,"startColumn":6,"startRow":92},"type":"expr"},{"text":"(","structure":[],"parent":1166,"id":1167,"range":{"startRow":92,"endRow":92,"startColumn":6,"endColumn":7},"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"parent":1166,"range":{"startColumn":7,"endColumn":15,"endRow":92,"startRow":92},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"name":"Count","value":{"text":"2"}}],"type":"collection","id":1168,"text":"LabeledExprList"},{"parent":1168,"range":{"endColumn":9,"startColumn":7,"startRow":92,"endRow":92},"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":1169,"type":"other"},{"parent":1169,"range":{"endColumn":8,"startRow":92,"startColumn":7,"endRow":92},"text":"IntegerLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("0")","text":"0"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"id":1170,"type":"expr"},{"text":"0","parent":1170,"structure":[],"id":1171,"range":{"endColumn":8,"startRow":92,"endRow":92,"startColumn":7},"token":{"kind":"integerLiteral("0")","leadingTrivia":"","trailingTrivia":""},"type":"other"},{"text":",","parent":1169,"structure":[],"id":1172,"range":{"endColumn":9,"startRow":92,"endRow":92,"startColumn":8},"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other"},{"parent":1168,"id":1173,"text":"LabeledExpr","type":"other","range":{"startColumn":10,"endColumn":15,"endRow":92,"startRow":92},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"PatternExprSyntax","value":{"text":"PatternExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"parent":1173,"id":1174,"text":"PatternExpr","type":"expr","range":{"startRow":92,"startColumn":10,"endRow":92,"endColumn":15},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"ValueBindingPatternSyntax"},"ref":"ValueBindingPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedAfterPattern"}]},{"parent":1174,"id":1175,"text":"ValueBindingPattern","type":"pattern","range":{"endRow":92,"startColumn":10,"endColumn":15,"startRow":92},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndPattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedAfterPattern"}]},{"text":"let","structure":[],"parent":1175,"id":1176,"range":{"startRow":92,"endRow":92,"endColumn":13,"startColumn":10},"token":{"kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other"},{"id":1177,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("y")","text":"y"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"parent":1175,"text":"IdentifierPattern","range":{"startRow":92,"endRow":92,"endColumn":15,"startColumn":14},"type":"pattern"},{"text":"y","structure":[],"parent":1177,"id":1178,"range":{"startRow":92,"endRow":92,"endColumn":15,"startColumn":14},"token":{"kind":"identifier("y")","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"text":")","structure":[],"parent":1166,"id":1179,"range":{"startRow":92,"endRow":92,"endColumn":16,"startColumn":15},"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"text":":","structure":[],"parent":1161,"id":1180,"range":{"startRow":92,"endRow":92,"endColumn":17,"startColumn":16},"token":{"kind":"colon","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"id":1181,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":1160,"text":"CodeBlockItemList","range":{"startRow":93,"endRow":93,"endColumn":50,"startColumn":5},"type":"collection"},{"id":1182,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":1181,"text":"CodeBlockItem","range":{"endRow":93,"startRow":93,"endColumn":50,"startColumn":5},"type":"other"},{"text":"FunctionCallExpr","range":{"endRow":93,"endColumn":50,"startRow":93,"startColumn":5},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":1183,"type":"expr","parent":1182},{"text":"DeclReferenceExpr","range":{"startColumn":5,"startRow":93,"endRow":93,"endColumn":10},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1184,"type":"expr","parent":1183},{"text":"print","parent":1184,"structure":[],"id":1185,"type":"other","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"range":{"startRow":93,"endRow":93,"endColumn":10,"startColumn":5}},{"text":"(","parent":1183,"structure":[],"id":1186,"type":"other","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":93,"endRow":93,"endColumn":11,"startColumn":10}},{"range":{"startRow":93,"endRow":93,"endColumn":49,"startColumn":11},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"LabeledExprList","type":"collection","id":1187,"parent":1183},{"range":{"startRow":93,"endRow":93,"endColumn":49,"startColumn":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"LabeledExpr","type":"other","id":1188,"parent":1187},{"range":{"endColumn":49,"startColumn":11,"startRow":93,"endRow":93},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"text":"StringLiteralExpr","type":"expr","id":1189,"parent":1188},{"text":""","parent":1189,"structure":[],"id":1190,"type":"other","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"startColumn":11,"endRow":93,"startRow":93,"endColumn":12}},{"type":"collection","parent":1189,"range":{"startColumn":12,"endRow":93,"startRow":93,"endColumn":48},"id":1191,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"text":"StringLiteralSegmentList"},{"type":"other","parent":1191,"range":{"startColumn":12,"endRow":93,"startRow":93,"endColumn":44},"id":1192,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("on the y-axis with a y value of ")","text":"on the y-axis with a y value of "},"name":"content"},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment"},{"text":"on␣<\/span>the␣<\/span>y-axis␣<\/span>with␣<\/span>a␣<\/span>y␣<\/span>value␣<\/span>of␣<\/span>","parent":1192,"structure":[],"id":1193,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("on the y-axis with a y value of ")"},"range":{"startRow":93,"endRow":93,"endColumn":44,"startColumn":12}},{"parent":1191,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","id":1194,"text":"ExpressionSegment","range":{"startRow":93,"endRow":93,"endColumn":48,"startColumn":44}},{"text":"\\","parent":1194,"structure":[],"id":1195,"type":"other","token":{"leadingTrivia":"","kind":"backslash","trailingTrivia":""},"range":{"startRow":93,"endRow":93,"startColumn":44,"endColumn":45}},{"text":"(","parent":1194,"structure":[],"id":1196,"type":"other","token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"range":{"startRow":93,"endRow":93,"startColumn":45,"endColumn":46}},{"parent":1194,"range":{"endRow":93,"startRow":93,"endColumn":47,"startColumn":46},"id":1197,"text":"LabeledExprList","type":"collection","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":1197,"text":"LabeledExpr","range":{"endColumn":47,"startRow":93,"startColumn":46,"endRow":93},"id":1198},{"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("y")","text":"y"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":1198,"text":"DeclReferenceExpr","range":{"endColumn":47,"startRow":93,"startColumn":46,"endRow":93},"id":1199},{"text":"y","parent":1199,"structure":[],"id":1200,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("y")"},"range":{"startRow":93,"startColumn":46,"endColumn":47,"endRow":93}},{"text":")","parent":1194,"structure":[],"id":1201,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"endColumn":48,"endRow":93,"startRow":93,"startColumn":47}},{"type":"other","range":{"endColumn":48,"endRow":93,"startRow":93,"startColumn":48},"id":1202,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"parent":1191,"text":"StringSegment"},{"text":"","parent":1202,"structure":[],"id":1203,"type":"other","token":{"kind":"stringSegment("")","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":48,"endRow":93,"endColumn":48,"startRow":93}},{"text":""","parent":1189,"structure":[],"id":1204,"type":"other","token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":48,"endRow":93,"endColumn":49,"startRow":93}},{"text":")","parent":1183,"structure":[],"id":1205,"type":"other","token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":49,"endRow":93,"endColumn":50,"startRow":93}},{"type":"collection","range":{"startColumn":50,"endRow":93,"endColumn":50,"startRow":93},"id":1206,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":1183,"text":"MultipleTrailingClosureElementList"},{"type":"other","range":{"startRow":94,"startColumn":1,"endRow":95,"endColumn":44},"id":1207,"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"SwitchCaseLabelSyntax"},"ref":"SwitchCaseLabelSyntax"},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"parent":1112,"text":"SwitchCase"},{"text":"SwitchCaseLabel","range":{"endRow":94,"endColumn":17,"startColumn":1,"startRow":94},"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","ref":"SwitchCaseItemListSyntax","value":{"text":"SwitchCaseItemListSyntax"}},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"id":1208,"type":"other","parent":1207},{"text":"case","parent":1208,"structure":[],"id":1209,"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.case)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"range":{"endRow":94,"endColumn":5,"startColumn":1,"startRow":94}},{"text":"SwitchCaseItemList","range":{"endRow":94,"endColumn":16,"startColumn":6,"startRow":94},"structure":[{"value":{"text":"SwitchCaseItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":1210,"type":"collection","parent":1208},{"text":"SwitchCaseItem","range":{"startRow":94,"startColumn":6,"endRow":94,"endColumn":16},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"ValueBindingPatternSyntax"},"ref":"ValueBindingPatternSyntax"},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":1211,"type":"other","parent":1210},{"text":"ValueBindingPattern","range":{"endRow":94,"endColumn":16,"startColumn":6,"startRow":94},"parent":1211,"id":1212,"structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"name":"pattern","ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedAfterPattern","value":{"text":"nil"}}],"type":"pattern"},{"text":"let","parent":1212,"structure":[],"id":1213,"type":"other","token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"range":{"startColumn":6,"endRow":94,"startRow":94,"endColumn":9}},{"text":"ExpressionPattern","range":{"startColumn":10,"endRow":94,"startRow":94,"endColumn":16},"parent":1212,"id":1214,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"TupleExprSyntax"},"name":"expression","ref":"TupleExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"pattern"},{"text":"TupleExpr","range":{"endRow":94,"startRow":94,"startColumn":10,"endColumn":16},"parent":1214,"id":1215,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"ref":"LabeledExprListSyntax","name":"elements","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenElementsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"type":"expr"},{"text":"(","parent":1215,"structure":[],"id":1216,"type":"other","token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":10,"startRow":94,"endColumn":11,"endRow":94}},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}],"range":{"startColumn":11,"startRow":94,"endColumn":15,"endRow":94},"type":"collection","parent":1215,"id":1217,"text":"LabeledExprList"},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"PatternExprSyntax","value":{"text":"PatternExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"startColumn":11,"endRow":94,"startRow":94,"endColumn":13},"type":"other","parent":1217,"id":1218,"text":"LabeledExpr"},{"text":"PatternExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedAfterPattern"}],"type":"expr","id":1219,"parent":1218,"range":{"startRow":94,"endRow":94,"startColumn":11,"endColumn":12}},{"text":"IdentifierPattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("x")","text":"x"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","id":1220,"parent":1219,"range":{"startRow":94,"startColumn":11,"endRow":94,"endColumn":12}},{"text":"x","parent":1220,"structure":[],"id":1221,"type":"other","token":{"kind":"identifier("x")","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":94,"endRow":94,"endColumn":12,"startColumn":11}},{"text":",","parent":1218,"structure":[],"id":1222,"type":"other","token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":94,"endRow":94,"endColumn":13,"startColumn":12}},{"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"PatternExprSyntax","value":{"text":"PatternExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":1223,"parent":1217,"range":{"startRow":94,"endRow":94,"endColumn":15,"startColumn":14}},{"range":{"endColumn":15,"startColumn":14,"endRow":94,"startRow":94},"text":"PatternExpr","type":"expr","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedAfterPattern","value":{"text":"nil"}}],"parent":1223,"id":1224},{"range":{"startRow":94,"startColumn":14,"endRow":94,"endColumn":15},"text":"IdentifierPattern","type":"pattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"y","kind":"identifier("y")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"parent":1224,"id":1225},{"text":"y","parent":1225,"structure":[],"id":1226,"type":"other","token":{"trailingTrivia":"","kind":"identifier("y")","leadingTrivia":""},"range":{"startColumn":14,"endColumn":15,"endRow":94,"startRow":94}},{"text":")","parent":1215,"structure":[],"id":1227,"type":"other","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"startColumn":15,"endColumn":16,"endRow":94,"startRow":94}},{"text":":","parent":1208,"structure":[],"id":1228,"type":"other","token":{"trailingTrivia":"","kind":"colon","leadingTrivia":""},"range":{"startColumn":16,"endColumn":17,"endRow":94,"startRow":94}},{"range":{"startColumn":5,"endColumn":44,"endRow":95,"startRow":95},"text":"CodeBlockItemList","type":"collection","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":1207,"id":1229},{"range":{"endColumn":44,"endRow":95,"startColumn":5,"startRow":95},"text":"CodeBlockItem","type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":1229,"id":1230},{"range":{"endRow":95,"startColumn":5,"endColumn":44,"startRow":95},"text":"FunctionCallExpr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","parent":1230,"id":1231},{"text":"DeclReferenceExpr","parent":1231,"id":1232,"range":{"endColumn":10,"endRow":95,"startColumn":5,"startRow":95},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"text":"print","parent":1232,"structure":[],"id":1233,"type":"other","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")","trailingTrivia":""},"range":{"endRow":95,"endColumn":10,"startColumn":5,"startRow":95}},{"text":"(","parent":1231,"structure":[],"id":1234,"type":"other","token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"range":{"endRow":95,"endColumn":11,"startColumn":10,"startRow":95}},{"text":"LabeledExprList","parent":1231,"id":1235,"range":{"endRow":95,"endColumn":43,"startColumn":11,"startRow":95},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"text":"LabeledExpr","parent":1235,"id":1236,"range":{"endRow":95,"startColumn":11,"startRow":95,"endColumn":43},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"range":{"startRow":95,"startColumn":11,"endRow":95,"endColumn":43},"text":"StringLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","id":1237,"parent":1236},{"text":""","structure":[],"type":"other","parent":1237,"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":11,"startRow":95,"endRow":95,"endColumn":12},"id":1238},{"id":1239,"text":"StringLiteralSegmentList","range":{"startColumn":12,"endColumn":42,"startRow":95,"endRow":95},"structure":[{"name":"Element","value":{"text":"Element"}},{"value":{"text":"5"},"name":"Count"}],"type":"collection","parent":1237},{"text":"StringSegment","parent":1239,"type":"other","range":{"endColumn":31,"startColumn":12,"endRow":95,"startRow":95},"id":1240,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("somewhere else at (")","text":"somewhere else at ("},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"text":"somewhere␣<\/span>else␣<\/span>at␣<\/span>(","structure":[],"type":"other","parent":1240,"token":{"trailingTrivia":"","kind":"stringSegment("somewhere else at (")","leadingTrivia":""},"range":{"endRow":95,"endColumn":31,"startRow":95,"startColumn":12},"id":1241},{"text":"ExpressionSegment","parent":1239,"type":"other","range":{"endRow":95,"endColumn":35,"startRow":95,"startColumn":31},"id":1242,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"text":"\\","structure":[],"type":"other","parent":1242,"token":{"kind":"backslash","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":95,"startColumn":31,"endRow":95,"endColumn":32},"id":1243},{"text":"(","structure":[],"type":"other","parent":1242,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":95,"startColumn":32,"endRow":95,"endColumn":33},"id":1244},{"parent":1242,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"LabeledExprList","type":"collection","id":1245,"range":{"startRow":95,"startColumn":33,"endRow":95,"endColumn":34}},{"parent":1245,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"LabeledExpr","type":"other","id":1246,"range":{"startColumn":33,"endColumn":34,"startRow":95,"endRow":95}},{"parent":1246,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"x","kind":"identifier("x")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"text":"DeclReferenceExpr","type":"expr","id":1247,"range":{"startRow":95,"startColumn":33,"endRow":95,"endColumn":34}},{"text":"x","structure":[],"type":"other","parent":1247,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("x")"},"range":{"endRow":95,"startRow":95,"endColumn":34,"startColumn":33},"id":1248},{"text":")","structure":[],"type":"other","parent":1242,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"endRow":95,"startRow":95,"endColumn":35,"startColumn":34},"id":1249},{"type":"other","id":1250,"parent":1239,"text":"StringSegment","range":{"endRow":95,"startRow":95,"endColumn":37,"startColumn":35},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(", ")","text":", "}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"text":",␣<\/span>","structure":[],"type":"other","parent":1250,"token":{"leadingTrivia":"","kind":"stringSegment(", ")","trailingTrivia":""},"range":{"endRow":95,"endColumn":37,"startColumn":35,"startRow":95},"id":1251},{"type":"other","id":1252,"parent":1239,"text":"ExpressionSegment","range":{"endRow":95,"endColumn":41,"startColumn":37,"startRow":95},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"text":"\\","structure":[],"type":"other","parent":1252,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"range":{"startRow":95,"startColumn":37,"endColumn":38,"endRow":95},"id":1253},{"text":"(","structure":[],"type":"other","parent":1252,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"startRow":95,"startColumn":38,"endColumn":39,"endRow":95},"id":1254},{"type":"collection","range":{"startRow":95,"startColumn":39,"endColumn":40,"endRow":95},"parent":1252,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"LabeledExprList","id":1255},{"type":"other","range":{"endRow":95,"endColumn":40,"startRow":95,"startColumn":39},"parent":1255,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"LabeledExpr","id":1256},{"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("y")","text":"y"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","id":1257,"range":{"endRow":95,"startColumn":39,"startRow":95,"endColumn":40},"parent":1256},{"text":"y","structure":[],"type":"other","parent":1257,"token":{"leadingTrivia":"","kind":"identifier("y")","trailingTrivia":""},"range":{"endRow":95,"endColumn":40,"startColumn":39,"startRow":95},"id":1258},{"text":")","structure":[],"type":"other","parent":1252,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"range":{"endRow":95,"endColumn":41,"startColumn":40,"startRow":95},"id":1259},{"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(")")","text":")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","id":1260,"range":{"endRow":95,"endColumn":42,"startColumn":41,"startRow":95},"parent":1239},{"text":")","structure":[],"type":"other","parent":1260,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(")")"},"range":{"startRow":95,"endRow":95,"startColumn":41,"endColumn":42},"id":1261},{"text":""","structure":[],"type":"other","parent":1237,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":95,"endRow":95,"startColumn":42,"endColumn":43},"id":1262},{"text":")","structure":[],"type":"other","parent":1231,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"startRow":95,"endRow":95,"startColumn":43,"endColumn":44},"id":1263},{"text":"MultipleTrailingClosureElementList","range":{"endColumn":44,"startRow":95,"startColumn":44,"endRow":95},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"value":{"text":"0"},"name":"Count"}],"id":1264,"parent":1231,"type":"collection"},{"text":"}","structure":[],"type":"other","parent":1107,"token":{"leadingTrivia":"↲<\/span>","kind":"rightBrace","trailingTrivia":""},"range":{"endRow":96,"startColumn":1,"startRow":96,"endColumn":2},"id":1265},{"parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":1266,"type":"other","range":{"endRow":100,"startColumn":1,"startRow":100,"endColumn":26},"text":"CodeBlockItem"},{"parent":1266,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":1267,"type":"decl","range":{"startColumn":1,"startRow":100,"endColumn":26,"endRow":100},"text":"VariableDecl"},{"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","parent":1267,"id":1268,"text":"AttributeList","range":{"startRow":96,"endRow":96,"endColumn":2,"startColumn":2}},{"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","parent":1267,"id":1269,"text":"DeclModifierList","range":{"startColumn":2,"endRow":96,"endColumn":2,"startRow":96}},{"text":"let","structure":[],"type":"other","parent":1267,"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Fallthrough<\/span>↲<\/span>\/\/␣<\/span>Using␣<\/span>fallthrough␣<\/span>in␣<\/span>switch<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"range":{"startRow":100,"startColumn":1,"endRow":100,"endColumn":4},"id":1270},{"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","parent":1267,"id":1271,"text":"PatternBindingList","range":{"startRow":100,"startColumn":5,"endRow":100,"endColumn":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":1271,"id":1272,"text":"PatternBinding","range":{"startColumn":5,"startRow":100,"endRow":100,"endColumn":26}},{"range":{"endRow":100,"startColumn":5,"endColumn":22,"startRow":100},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"integerToDescribe","kind":"identifier("integerToDescribe")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"parent":1272,"type":"pattern","text":"IdentifierPattern","id":1273},{"text":"integerToDescribe","structure":[],"type":"other","parent":1273,"token":{"kind":"identifier("integerToDescribe")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"startRow":100,"endRow":100,"endColumn":22,"startColumn":5},"id":1274},{"range":{"startRow":100,"endRow":100,"endColumn":26,"startColumn":23},"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"parent":1272,"type":"other","text":"InitializerClause","id":1275},{"text":"=","structure":[],"type":"other","parent":1275,"token":{"kind":"equal","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"endRow":100,"endColumn":24,"startRow":100,"startColumn":23},"id":1276},{"parent":1275,"text":"IntegerLiteralExpr","range":{"startColumn":25,"startRow":100,"endColumn":26,"endRow":100},"id":1277,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("5")","text":"5"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr"},{"text":"5","structure":[],"type":"other","parent":1277,"token":{"leadingTrivia":"","kind":"integerLiteral("5")","trailingTrivia":""},"range":{"startColumn":25,"endRow":100,"startRow":100,"endColumn":26},"id":1278},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"VariableDeclSyntax","name":"item","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"range":{"startColumn":1,"endRow":101,"startRow":101,"endColumn":55},"parent":1,"text":"CodeBlockItem","id":1279,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax","name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"range":{"startRow":101,"startColumn":1,"endColumn":55,"endRow":101},"parent":1279,"text":"VariableDecl","id":1280,"type":"decl"},{"type":"collection","parent":1280,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"range":{"endRow":100,"startColumn":26,"startRow":100,"endColumn":26},"text":"AttributeList","id":1281},{"type":"collection","parent":1280,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"range":{"endRow":100,"endColumn":26,"startRow":100,"startColumn":26},"text":"DeclModifierList","id":1282},{"text":"var","structure":[],"type":"other","parent":1280,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)"},"range":{"startRow":101,"startColumn":1,"endColumn":4,"endRow":101},"id":1283},{"type":"collection","parent":1280,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"startRow":101,"startColumn":5,"endColumn":55,"endRow":101},"text":"PatternBindingList","id":1284},{"type":"other","parent":1284,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endRow":101,"startRow":101,"endColumn":55,"startColumn":5},"text":"PatternBinding","id":1285},{"text":"IdentifierPattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("description")","text":"description"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":1286,"parent":1285,"range":{"startColumn":5,"endRow":101,"startRow":101,"endColumn":16},"type":"pattern"},{"text":"description","structure":[],"type":"other","parent":1286,"token":{"kind":"identifier("description")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":101,"startColumn":5,"endColumn":16,"endRow":101},"id":1287},{"text":"InitializerClause","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":1288,"parent":1285,"range":{"startRow":101,"startColumn":17,"endColumn":55,"endRow":101},"type":"other"},{"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":"=","range":{"startRow":101,"endRow":101,"startColumn":17,"endColumn":18},"id":1289,"type":"other","structure":[],"parent":1288},{"range":{"startColumn":19,"startRow":101,"endColumn":55,"endRow":101},"id":1290,"text":"StringLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","parent":1288},{"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"startRow":101,"startColumn":19,"endRow":101,"endColumn":20},"text":""","id":1291,"type":"other","structure":[],"parent":1290},{"range":{"startRow":101,"startColumn":20,"endRow":101,"endColumn":54},"id":1292,"text":"StringLiteralSegmentList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"type":"collection","parent":1290},{"range":{"startRow":101,"endColumn":31,"endRow":101,"startColumn":20},"id":1293,"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("The number ")","text":"The number "}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","parent":1292},{"token":{"leadingTrivia":"","kind":"stringSegment("The number ")","trailingTrivia":""},"text":"The␣<\/span>number␣<\/span>","range":{"startRow":101,"endColumn":31,"startColumn":20,"endRow":101},"id":1294,"type":"other","parent":1293,"structure":[]},{"type":"other","parent":1292,"text":"ExpressionSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"name":"expressions","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":1295,"range":{"startRow":101,"endColumn":51,"startColumn":31,"endRow":101}},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"text":"\\","range":{"startRow":101,"endRow":101,"endColumn":32,"startColumn":31},"id":1296,"type":"other","parent":1295,"structure":[]},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"text":"(","range":{"startRow":101,"endRow":101,"endColumn":33,"startColumn":32},"id":1297,"type":"other","parent":1295,"structure":[]},{"parent":1295,"text":"LabeledExprList","type":"collection","range":{"endColumn":50,"startRow":101,"startColumn":33,"endRow":101},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"value":{"text":"1"},"name":"Count"}],"id":1298},{"parent":1298,"range":{"endRow":101,"endColumn":50,"startRow":101,"startColumn":33},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","text":"LabeledExpr","id":1299},{"parent":1299,"range":{"startRow":101,"endColumn":50,"startColumn":33,"endRow":101},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"integerToDescribe","kind":"identifier("integerToDescribe")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":1300},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("integerToDescribe")"},"range":{"endRow":101,"startColumn":33,"startRow":101,"endColumn":50},"text":"integerToDescribe","id":1301,"type":"other","parent":1300,"structure":[]},{"token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endColumn":51,"startColumn":50,"endRow":101,"startRow":101},"text":")","id":1302,"type":"other","parent":1295,"structure":[]},{"type":"other","range":{"endColumn":54,"startColumn":51,"endRow":101,"startRow":101},"parent":1292,"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(" is")","text":" is"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":1303},{"token":{"leadingTrivia":"","kind":"stringSegment(" is")","trailingTrivia":""},"range":{"endRow":101,"startRow":101,"startColumn":51,"endColumn":54},"text":"␣<\/span>is","id":1304,"type":"other","parent":1303,"structure":[]},{"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"range":{"endRow":101,"startRow":101,"startColumn":54,"endColumn":55},"text":""","id":1305,"type":"other","parent":1290,"structure":[]},{"type":"other","range":{"endRow":108,"startRow":102,"startColumn":1,"endColumn":2},"parent":1,"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ExpressionStmtSyntax"},"ref":"ExpressionStmtSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":1306},{"type":"other","range":{"startRow":102,"endColumn":2,"startColumn":1,"endRow":108},"parent":1306,"text":"ExpressionStmt","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"SwitchExprSyntax","value":{"text":"SwitchExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"id":1307},{"type":"expr","range":{"startColumn":1,"endColumn":2,"endRow":108,"startRow":102},"parent":1307,"text":"SwitchExpr","structure":[{"name":"unexpectedBeforeSwitchKeyword","value":{"text":"nil"}},{"name":"switchKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.switch)","text":"switch"}},{"name":"unexpectedBetweenSwitchKeywordAndSubject","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"subject","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenSubjectAndLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndCases","value":{"text":"nil"}},{"ref":"SwitchCaseListSyntax","name":"cases","value":{"text":"SwitchCaseListSyntax"}},{"name":"unexpectedBetweenCasesAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":1308},{"token":{"kind":"keyword(SwiftSyntax.Keyword.switch)","leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>"},"text":"switch","range":{"endRow":102,"endColumn":7,"startColumn":1,"startRow":102},"id":1309,"type":"other","parent":1308,"structure":[]},{"parent":1308,"text":"DeclReferenceExpr","id":1310,"type":"expr","range":{"endRow":102,"endColumn":25,"startColumn":8,"startRow":102},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("integerToDescribe")","text":"integerToDescribe"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("integerToDescribe")"},"range":{"startColumn":8,"endRow":102,"startRow":102,"endColumn":25},"text":"integerToDescribe","id":1311,"type":"other","structure":[],"parent":1310},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"startColumn":26,"endRow":102,"startRow":102,"endColumn":27},"text":"{","id":1312,"type":"other","structure":[],"parent":1308},{"range":{"startColumn":1,"endRow":107,"startRow":103,"endColumn":34},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"2"}}],"type":"collection","id":1313,"parent":1308,"text":"SwitchCaseList"},{"range":{"startRow":103,"startColumn":1,"endRow":105,"endColumn":16},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeAndLabel"},{"ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedAfterStatements"}],"type":"other","id":1314,"parent":1313,"text":"SwitchCase"},{"range":{"startRow":103,"endRow":103,"startColumn":1,"endColumn":33},"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"ref":"SwitchCaseItemListSyntax","name":"caseItems","value":{"text":"SwitchCaseItemListSyntax"}},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"type":"other","id":1315,"parent":1314,"text":"SwitchCaseLabel"},{"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)"},"range":{"startColumn":1,"startRow":103,"endColumn":5,"endRow":103},"text":"case","id":1316,"type":"other","structure":[],"parent":1315},{"structure":[{"name":"Element","value":{"text":"SwitchCaseItemSyntax"}},{"name":"Count","value":{"text":"8"}}],"parent":1315,"type":"collection","range":{"startColumn":6,"startRow":103,"endColumn":32,"endRow":103},"text":"SwitchCaseItemList","id":1317},{"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"ExpressionPatternSyntax"},"ref":"ExpressionPatternSyntax"},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1317,"type":"other","range":{"startRow":103,"startColumn":6,"endRow":103,"endColumn":8},"text":"SwitchCaseItem","id":1318},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"parent":1318,"type":"pattern","range":{"endColumn":7,"endRow":103,"startColumn":6,"startRow":103},"text":"ExpressionPattern","id":1319},{"id":1320,"type":"expr","range":{"startRow":103,"endRow":103,"startColumn":6,"endColumn":7},"parent":1319,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"2","kind":"integerLiteral("2")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"text":"IntegerLiteralExpr"},{"token":{"kind":"integerLiteral("2")","trailingTrivia":"","leadingTrivia":""},"range":{"endRow":103,"startColumn":6,"startRow":103,"endColumn":7},"text":"2","id":1321,"type":"other","parent":1320,"structure":[]},{"token":{"kind":"comma","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"endRow":103,"startColumn":7,"startRow":103,"endColumn":8},"text":",","id":1322,"type":"other","parent":1318,"structure":[]},{"id":1323,"type":"other","range":{"endRow":103,"startColumn":9,"startRow":103,"endColumn":11},"parent":1317,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"SwitchCaseItem"},{"id":1324,"type":"pattern","range":{"endRow":103,"startColumn":9,"startRow":103,"endColumn":10},"parent":1323,"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"expression","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"text":"ExpressionPattern"},{"range":{"startColumn":9,"startRow":103,"endColumn":10,"endRow":103},"id":1325,"parent":1324,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"3","kind":"integerLiteral("3")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr"},{"token":{"trailingTrivia":"","kind":"integerLiteral("3")","leadingTrivia":""},"range":{"endRow":103,"endColumn":10,"startRow":103,"startColumn":9},"text":"3","id":1326,"type":"other","parent":1325,"structure":[]},{"token":{"trailingTrivia":"␣<\/span>","kind":"comma","leadingTrivia":""},"range":{"endRow":103,"endColumn":11,"startRow":103,"startColumn":10},"text":",","id":1327,"type":"other","parent":1323,"structure":[]},{"range":{"endRow":103,"endColumn":14,"startRow":103,"startColumn":12},"id":1328,"parent":1317,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"ExpressionPatternSyntax"},"name":"pattern","ref":"ExpressionPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"SwitchCaseItem"},{"range":{"startRow":103,"startColumn":12,"endRow":103,"endColumn":13},"id":1329,"parent":1328,"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"pattern","text":"ExpressionPattern"},{"range":{"endColumn":13,"startRow":103,"startColumn":12,"endRow":103},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"5","kind":"integerLiteral("5")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":1329,"type":"expr","id":1330,"text":"IntegerLiteralExpr"},{"token":{"kind":"integerLiteral("5")","leadingTrivia":"","trailingTrivia":""},"range":{"startColumn":12,"endRow":103,"endColumn":13,"startRow":103},"text":"5","id":1331,"type":"other","structure":[],"parent":1330},{"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startColumn":13,"endRow":103,"endColumn":14,"startRow":103},"text":",","id":1332,"type":"other","structure":[],"parent":1328},{"range":{"startColumn":15,"endRow":103,"endColumn":17,"startRow":103},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1317,"type":"other","id":1333,"text":"SwitchCaseItem"},{"range":{"endRow":103,"startRow":103,"startColumn":15,"endColumn":16},"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"parent":1333,"type":"pattern","id":1334,"text":"ExpressionPattern"},{"type":"expr","text":"IntegerLiteralExpr","parent":1334,"range":{"endRow":103,"startColumn":15,"endColumn":16,"startRow":103},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("7")","text":"7"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":1335},{"token":{"kind":"integerLiteral("7")","leadingTrivia":"","trailingTrivia":""},"text":"7","range":{"endRow":103,"endColumn":16,"startRow":103,"startColumn":15},"id":1336,"type":"other","parent":1335,"structure":[]},{"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":",","range":{"endRow":103,"endColumn":17,"startRow":103,"startColumn":16},"id":1337,"type":"other","parent":1333,"structure":[]},{"type":"other","text":"SwitchCaseItem","parent":1317,"range":{"endRow":103,"endColumn":21,"startRow":103,"startColumn":18},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"ExpressionPatternSyntax"},"name":"pattern","ref":"ExpressionPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":1338},{"type":"pattern","text":"ExpressionPattern","parent":1338,"range":{"endColumn":20,"startColumn":18,"endRow":103,"startRow":103},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"id":1339},{"range":{"startColumn":18,"endRow":103,"startRow":103,"endColumn":20},"id":1340,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"11","kind":"integerLiteral("11")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"text":"IntegerLiteralExpr","parent":1339,"type":"expr"},{"token":{"kind":"integerLiteral("11")","trailingTrivia":"","leadingTrivia":""},"id":1341,"structure":[],"text":"11","parent":1340,"range":{"endColumn":20,"startRow":103,"startColumn":18,"endRow":103},"type":"other"},{"token":{"kind":"comma","trailingTrivia":"␣<\/span>","leadingTrivia":""},"id":1342,"structure":[],"text":",","parent":1338,"range":{"endColumn":21,"startRow":103,"startColumn":20,"endRow":103},"type":"other"},{"range":{"endColumn":25,"startRow":103,"startColumn":22,"endRow":103},"id":1343,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"SwitchCaseItem","parent":1317,"type":"other"},{"range":{"startColumn":22,"endRow":103,"endColumn":24,"startRow":103},"id":1344,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"text":"ExpressionPattern","parent":1343,"type":"pattern"},{"id":1345,"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"13","kind":"integerLiteral("13")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":1344,"range":{"startRow":103,"startColumn":22,"endColumn":24,"endRow":103},"text":"IntegerLiteralExpr"},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("13")"},"id":1346,"structure":[],"type":"other","parent":1345,"range":{"endColumn":24,"startRow":103,"startColumn":22,"endRow":103},"text":"13"},{"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"id":1347,"structure":[],"type":"other","parent":1343,"range":{"endColumn":25,"startRow":103,"startColumn":24,"endRow":103},"text":","},{"id":1348,"type":"other","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ExpressionPatternSyntax","name":"pattern","value":{"text":"ExpressionPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"kind":"comma","text":","}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1317,"range":{"endColumn":29,"startRow":103,"startColumn":26,"endRow":103},"text":"SwitchCaseItem"},{"id":1349,"type":"pattern","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"parent":1348,"range":{"startRow":103,"endColumn":28,"startColumn":26,"endRow":103},"text":"ExpressionPattern"},{"range":{"endRow":103,"startColumn":26,"startRow":103,"endColumn":28},"type":"expr","id":1350,"parent":1349,"text":"IntegerLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("17")","text":"17"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}]},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("17")"},"id":1351,"structure":[],"type":"other","parent":1350,"range":{"endRow":103,"endColumn":28,"startRow":103,"startColumn":26},"text":"17"},{"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"comma"},"id":1352,"structure":[],"type":"other","parent":1348,"range":{"endRow":103,"endColumn":29,"startRow":103,"startColumn":28},"text":","},{"range":{"endRow":103,"endColumn":32,"startRow":103,"startColumn":30},"type":"other","id":1353,"parent":1317,"text":"SwitchCaseItem","structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"ExpressionPatternSyntax"},"ref":"ExpressionPatternSyntax"},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"endRow":103,"endColumn":32,"startRow":103,"startColumn":30},"type":"pattern","id":1354,"parent":1353,"text":"ExpressionPattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"type":"expr","id":1355,"parent":1354,"range":{"startRow":103,"startColumn":30,"endRow":103,"endColumn":32},"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"19","kind":"integerLiteral("19")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"token":{"kind":"integerLiteral("19")","leadingTrivia":"","trailingTrivia":""},"id":1356,"structure":[],"type":"other","parent":1355,"range":{"endColumn":32,"endRow":103,"startRow":103,"startColumn":30},"text":"19"},{"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":""},"id":1357,"structure":[],"type":"other","parent":1315,"range":{"endColumn":33,"endRow":103,"startRow":103,"startColumn":32},"text":":"},{"type":"collection","id":1358,"parent":1314,"range":{"endColumn":16,"endRow":105,"startRow":104,"startColumn":5},"text":"CodeBlockItemList","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}]},{"type":"other","id":1359,"parent":1358,"range":{"endRow":104,"endColumn":47,"startRow":104,"startColumn":5},"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"type":"expr","id":1360,"parent":1359,"range":{"startColumn":5,"startRow":104,"endRow":104,"endColumn":47},"text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax","name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}]},{"range":{"startRow":104,"endColumn":16,"endRow":104,"startColumn":5},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"description","kind":"identifier("description")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":1360,"id":1361,"text":"DeclReferenceExpr"},{"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("description")"},"id":1362,"structure":[],"type":"other","parent":1361,"range":{"endRow":104,"endColumn":16,"startColumn":5,"startRow":104},"text":"description"},{"range":{"endRow":104,"endColumn":19,"startColumn":17,"startRow":104},"type":"expr","structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"+=","kind":"binaryOperator("+=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"parent":1360,"id":1363,"text":"BinaryOperatorExpr"},{"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"binaryOperator("+=")"},"id":1364,"structure":[],"type":"other","parent":1363,"range":{"endColumn":19,"endRow":104,"startRow":104,"startColumn":17},"text":"+="},{"parent":1360,"range":{"endRow":104,"endColumn":47,"startRow":104,"startColumn":20},"id":1365,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"text":"StringLiteralExpr","type":"expr"},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"id":1366,"structure":[],"parent":1365,"text":""","range":{"startRow":104,"startColumn":20,"endRow":104,"endColumn":21},"type":"other"},{"parent":1365,"range":{"startRow":104,"startColumn":21,"endRow":104,"endColumn":46},"id":1367,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"StringLiteralSegmentList","type":"collection"},{"parent":1367,"range":{"startColumn":21,"endColumn":46,"startRow":104,"endRow":104},"id":1368,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(" a prime number, and also")","text":" a prime number, and also"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"text":"StringSegment","type":"other"},{"token":{"leadingTrivia":"","kind":"stringSegment(" a prime number, and also")","trailingTrivia":""},"id":1369,"structure":[],"text":"␣<\/span>a␣<\/span>prime␣<\/span>number,␣<\/span>and␣<\/span>also","type":"other","parent":1368,"range":{"startRow":104,"startColumn":21,"endColumn":46,"endRow":104}},{"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"id":1370,"structure":[],"text":""","type":"other","parent":1365,"range":{"startRow":104,"startColumn":46,"endColumn":47,"endRow":104}},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"FallThroughStmtSyntax","value":{"text":"FallThroughStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","type":"other","parent":1358,"range":{"startRow":105,"startColumn":5,"endColumn":16,"endRow":105},"id":1371},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeFallthroughKeyword"},{"value":{"text":"fallthrough","kind":"keyword(SwiftSyntax.Keyword.fallthrough)"},"name":"fallthroughKeyword"},{"value":{"text":"nil"},"name":"unexpectedAfterFallthroughKeyword"}],"text":"FallThroughStmt","type":"other","parent":1371,"range":{"endRow":105,"startRow":105,"startColumn":5,"endColumn":16},"id":1372},{"token":{"kind":"keyword(SwiftSyntax.Keyword.fallthrough)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"id":1373,"structure":[],"text":"fallthrough","type":"other","parent":1372,"range":{"endRow":105,"startColumn":5,"startRow":105,"endColumn":16}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"value":{"text":"nil"},"name":"attribute"},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","ref":"SwitchDefaultLabelSyntax","value":{"text":"SwitchDefaultLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"text":"SwitchCase","type":"other","parent":1313,"range":{"endRow":107,"startColumn":1,"startRow":106,"endColumn":34},"id":1374},{"range":{"startColumn":1,"startRow":106,"endRow":106,"endColumn":9},"structure":[{"name":"unexpectedBeforeDefaultKeyword","value":{"text":"nil"}},{"name":"defaultKeyword","value":{"text":"default","kind":"keyword(SwiftSyntax.Keyword.default)"}},{"name":"unexpectedBetweenDefaultKeywordAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"text":"SwitchDefaultLabel","type":"other","parent":1374,"id":1375},{"token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.default)"},"id":1376,"structure":[],"text":"default","type":"other","range":{"endRow":106,"endColumn":8,"startRow":106,"startColumn":1},"parent":1375},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"colon"},"id":1377,"structure":[],"text":":","type":"other","range":{"endRow":106,"endColumn":9,"startRow":106,"startColumn":8},"parent":1375},{"range":{"endRow":107,"endColumn":34,"startRow":107,"startColumn":5},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"CodeBlockItemList","type":"collection","parent":1374,"id":1378},{"range":{"endColumn":34,"startColumn":5,"startRow":107,"endRow":107},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"InfixOperatorExprSyntax","name":"item","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","type":"other","parent":1378,"id":1379},{"text":"InfixOperatorExpr","id":1380,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"range":{"startColumn":5,"endColumn":34,"startRow":107,"endRow":107},"type":"expr","parent":1379},{"text":"DeclReferenceExpr","id":1381,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"description","kind":"identifier("description")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"endColumn":16,"startRow":107,"endRow":107,"startColumn":5},"type":"expr","parent":1380},{"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("description")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"id":1382,"structure":[],"text":"description","type":"other","range":{"startColumn":5,"startRow":107,"endColumn":16,"endRow":107},"parent":1381},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"text":"+=","kind":"binaryOperator("+=")"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"id":1383,"text":"BinaryOperatorExpr","range":{"startColumn":17,"startRow":107,"endColumn":19,"endRow":107},"type":"expr","parent":1380},{"token":{"trailingTrivia":"␣<\/span>","kind":"binaryOperator("+=")","leadingTrivia":""},"id":1384,"structure":[],"text":"+=","type":"other","range":{"endRow":107,"startRow":107,"endColumn":19,"startColumn":17},"parent":1383},{"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":1385,"text":"StringLiteralExpr","range":{"endRow":107,"startRow":107,"endColumn":34,"startColumn":20},"type":"expr","parent":1380},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"id":1386,"structure":[],"parent":1385,"type":"other","range":{"startColumn":20,"endRow":107,"endColumn":21,"startRow":107},"text":"""},{"parent":1385,"range":{"startColumn":21,"endRow":107,"endColumn":33,"startRow":107},"type":"collection","id":1387,"text":"StringLiteralSegmentList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"parent":1387,"range":{"endRow":107,"startColumn":21,"endColumn":33,"startRow":107},"type":"other","id":1388,"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":" an integer.","kind":"stringSegment(" an integer.")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"token":{"kind":"stringSegment(" an integer.")","trailingTrivia":"","leadingTrivia":""},"id":1389,"structure":[],"parent":1388,"type":"other","range":{"startRow":107,"startColumn":21,"endRow":107,"endColumn":33},"text":"␣<\/span>an␣<\/span>integer."},{"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"id":1390,"structure":[],"parent":1385,"type":"other","range":{"startRow":107,"startColumn":33,"endRow":107,"endColumn":34},"text":"""},{"type":"other","range":{"startRow":108,"startColumn":1,"endRow":108,"endColumn":2},"id":1391,"token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":"↲<\/span>"},"text":"}","structure":[],"parent":1308},{"parent":1,"range":{"startRow":109,"startColumn":1,"endRow":109,"endColumn":19},"type":"other","id":1392,"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"name":"item","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"parent":1392,"range":{"endRow":109,"endColumn":19,"startRow":109,"startColumn":1},"type":"expr","id":1393,"text":"FunctionCallExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"text":"DeclReferenceExpr","type":"expr","range":{"endRow":109,"endColumn":6,"startRow":109,"startColumn":1},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1394,"parent":1393},{"type":"other","id":1395,"range":{"startRow":109,"endRow":109,"startColumn":1,"endColumn":6},"token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>","trailingTrivia":""},"structure":[],"text":"print","parent":1394},{"type":"other","id":1396,"range":{"startRow":109,"endRow":109,"startColumn":6,"endColumn":7},"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"(","parent":1393},{"id":1397,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":1393,"text":"LabeledExprList","range":{"startRow":109,"endRow":109,"startColumn":7,"endColumn":18},"type":"collection"},{"id":1398,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1397,"text":"LabeledExpr","range":{"endColumn":18,"startRow":109,"endRow":109,"startColumn":7},"type":"other"},{"id":1399,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"value":{"text":"description","kind":"identifier("description")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":1398,"text":"DeclReferenceExpr","range":{"endRow":109,"endColumn":18,"startColumn":7,"startRow":109},"type":"expr"},{"type":"other","range":{"endColumn":18,"endRow":109,"startRow":109,"startColumn":7},"id":1400,"token":{"kind":"identifier("description")","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"description","parent":1399},{"type":"other","range":{"endColumn":19,"endRow":109,"startRow":109,"startColumn":18},"id":1401,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":")","parent":1393},{"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":1393,"range":{"endColumn":19,"endRow":109,"startRow":109,"startColumn":19},"type":"collection","id":1402,"text":"MultipleTrailingClosureElementList"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":1,"range":{"endColumn":21,"startRow":113,"endRow":113,"startColumn":1},"type":"other","id":1403,"text":"CodeBlockItem"},{"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax","name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"parent":1403,"range":{"startRow":113,"startColumn":1,"endRow":113,"endColumn":21},"type":"decl","id":1404,"text":"VariableDecl"},{"parent":1404,"text":"AttributeList","id":1405,"range":{"startRow":109,"endRow":109,"startColumn":19,"endColumn":19},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection"},{"parent":1404,"text":"DeclModifierList","id":1406,"range":{"startColumn":19,"startRow":109,"endRow":109,"endColumn":19},"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection"},{"type":"other","id":1407,"range":{"endColumn":4,"endRow":113,"startColumn":1,"startRow":113},"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Labeled␣<\/span>Statements<\/span>↲<\/span>\/\/␣<\/span>Using␣<\/span>labeled␣<\/span>statements␣<\/span>with␣<\/span>break<\/span>↲<\/span>"},"text":"let","structure":[],"parent":1404},{"parent":1404,"text":"PatternBindingList","id":1408,"range":{"endColumn":21,"endRow":113,"startColumn":5,"startRow":113},"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection"},{"parent":1408,"text":"PatternBinding","id":1409,"range":{"startColumn":5,"endRow":113,"startRow":113,"endColumn":21},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"type":"pattern","id":1410,"text":"IdentifierPattern","range":{"endRow":113,"endColumn":16,"startColumn":5,"startRow":113},"parent":1409,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("finalSquare")","text":"finalSquare"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"type":"other","id":1411,"range":{"startColumn":5,"endRow":113,"startRow":113,"endColumn":16},"token":{"kind":"identifier("finalSquare")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":"finalSquare","structure":[],"parent":1410},{"type":"other","id":1412,"text":"InitializerClause","range":{"startColumn":17,"endRow":113,"startRow":113,"endColumn":21},"parent":1409,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"type":"other","range":{"startRow":113,"endRow":113,"startColumn":17,"endColumn":18},"id":1413,"token":{"kind":"equal","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"text":"=","parent":1412},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"25","kind":"integerLiteral("25")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"startRow":113,"endRow":113,"startColumn":19,"endColumn":21},"type":"expr","id":1414,"text":"IntegerLiteralExpr","parent":1412},{"type":"other","range":{"startColumn":19,"startRow":113,"endRow":113,"endColumn":21},"id":1415,"token":{"leadingTrivia":"","kind":"integerLiteral("25")","trailingTrivia":""},"structure":[],"text":"25","parent":1414},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"range":{"startColumn":1,"startRow":114,"endRow":114,"endColumn":56},"type":"other","id":1416,"text":"CodeBlockItem","parent":1},{"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"range":{"startRow":114,"startColumn":1,"endRow":114,"endColumn":56},"type":"decl","id":1417,"text":"VariableDecl","parent":1416},{"text":"AttributeList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":1417,"id":1418,"type":"collection","range":{"startColumn":21,"startRow":113,"endColumn":21,"endRow":113}},{"text":"DeclModifierList","structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":1417,"id":1419,"type":"collection","range":{"startColumn":21,"endRow":113,"startRow":113,"endColumn":21}},{"type":"other","id":1420,"range":{"startColumn":1,"startRow":114,"endRow":114,"endColumn":4},"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)","leadingTrivia":"↲<\/span>"},"text":"var","structure":[],"parent":1417},{"text":"PatternBindingList","structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":1417,"id":1421,"type":"collection","range":{"startColumn":5,"startRow":114,"endRow":114,"endColumn":56}},{"text":"PatternBinding","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":1422,"type":"other","parent":1421,"range":{"startColumn":5,"endRow":114,"endColumn":56,"startRow":114}},{"text":"IdentifierPattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("board")","text":"board"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":1423,"type":"pattern","parent":1422,"range":{"startRow":114,"startColumn":5,"endRow":114,"endColumn":10}},{"type":"other","id":1424,"range":{"startRow":114,"startColumn":5,"endColumn":10,"endRow":114},"token":{"kind":"identifier("board")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":"board","structure":[],"parent":1423},{"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"FunctionCallExprSyntax"},"name":"value","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"range":{"startRow":114,"endRow":114,"endColumn":56,"startColumn":11},"id":1425,"parent":1422,"text":"InitializerClause"},{"type":"other","range":{"startColumn":11,"endColumn":12,"startRow":114,"endRow":114},"id":1426,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"structure":[],"text":"=","parent":1425},{"type":"expr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"ArrayExprSyntax"},"ref":"ArrayExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"range":{"startColumn":13,"endColumn":56,"startRow":114,"endRow":114},"id":1427,"parent":1425,"text":"FunctionCallExpr"},{"structure":[{"name":"unexpectedBeforeLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"kind":"leftSquare","text":"["}},{"name":"unexpectedBetweenLeftSquareAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"ArrayElementListSyntax"},"ref":"ArrayElementListSyntax"},{"name":"unexpectedBetweenElementsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedAfterRightSquare","value":{"text":"nil"}}],"range":{"startRow":114,"startColumn":13,"endRow":114,"endColumn":18},"parent":1427,"type":"expr","id":1428,"text":"ArrayExpr"},{"type":"other","range":{"endRow":114,"endColumn":14,"startRow":114,"startColumn":13},"id":1429,"token":{"kind":"leftSquare","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"[","parent":1428},{"structure":[{"name":"Element","value":{"text":"ArrayElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"range":{"endRow":114,"endColumn":17,"startRow":114,"startColumn":14},"parent":1428,"type":"collection","id":1430,"text":"ArrayElementList"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"startRow":114,"startColumn":14,"endColumn":17,"endRow":114},"parent":1430,"type":"other","id":1431,"text":"ArrayElement"},{"type":"expr","range":{"endRow":114,"endColumn":17,"startRow":114,"startColumn":14},"parent":1431,"text":"DeclReferenceExpr","id":1432,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("Int")","text":"Int"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","range":{"startColumn":14,"endColumn":17,"startRow":114,"endRow":114},"id":1433,"token":{"leadingTrivia":"","kind":"identifier("Int")","trailingTrivia":""},"text":"Int","structure":[],"parent":1432},{"type":"other","range":{"startColumn":17,"endColumn":18,"startRow":114,"endRow":114},"id":1434,"token":{"leadingTrivia":"","kind":"rightSquare","trailingTrivia":""},"text":"]","structure":[],"parent":1428},{"type":"other","range":{"startColumn":18,"endColumn":19,"startRow":114,"endRow":114},"id":1435,"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"text":"(","structure":[],"parent":1427},{"type":"collection","range":{"startColumn":19,"endColumn":55,"startRow":114,"endRow":114},"parent":1427,"text":"LabeledExprList","id":1436,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}]},{"type":"other","range":{"endRow":114,"endColumn":32,"startRow":114,"startColumn":19},"parent":1436,"text":"LabeledExpr","id":1437,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"kind":"identifier("repeating")","text":"repeating"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"type":"other","id":1438,"range":{"startColumn":19,"startRow":114,"endRow":114,"endColumn":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("repeating")"},"text":"repeating","structure":[],"parent":1437},{"type":"other","id":1439,"range":{"startColumn":28,"startRow":114,"endRow":114,"endColumn":29},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"text":":","structure":[],"parent":1437},{"type":"expr","parent":1437,"text":"IntegerLiteralExpr","id":1440,"range":{"startColumn":30,"startRow":114,"endRow":114,"endColumn":31},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"type":"other","id":1441,"range":{"startColumn":30,"endRow":114,"startRow":114,"endColumn":31},"token":{"kind":"integerLiteral("0")","leadingTrivia":"","trailingTrivia":""},"text":"0","structure":[],"parent":1440},{"type":"other","id":1442,"range":{"startColumn":31,"endRow":114,"startRow":114,"endColumn":32},"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":",","structure":[],"parent":1437},{"type":"other","parent":1436,"text":"LabeledExpr","id":1443,"range":{"startColumn":33,"endRow":114,"startRow":114,"endColumn":55},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"count","kind":"identifier("count")"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"type":"other","range":{"startColumn":33,"startRow":114,"endColumn":38,"endRow":114},"id":1444,"token":{"kind":"identifier("count")","leadingTrivia":"","trailingTrivia":""},"text":"count","structure":[],"parent":1443},{"type":"other","parent":1443,"text":":","range":{"startColumn":38,"startRow":114,"endColumn":39,"endRow":114},"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":1445,"structure":[]},{"range":{"startColumn":40,"startRow":114,"endColumn":55,"endRow":114},"type":"expr","parent":1443,"id":1446,"text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}]},{"range":{"startColumn":40,"endRow":114,"endColumn":51,"startRow":114},"type":"expr","parent":1446,"id":1447,"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("finalSquare")","text":"finalSquare"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","parent":1447,"text":"finalSquare","range":{"startRow":114,"startColumn":40,"endColumn":51,"endRow":114},"token":{"leadingTrivia":"","kind":"identifier("finalSquare")","trailingTrivia":"␣<\/span>"},"structure":[],"id":1448},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator("+")","text":"+"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"type":"expr","text":"BinaryOperatorExpr","range":{"startRow":114,"startColumn":52,"endColumn":53,"endRow":114},"id":1449,"parent":1446},{"type":"other","parent":1449,"text":"+","range":{"startColumn":52,"endRow":114,"endColumn":53,"startRow":114},"token":{"kind":"binaryOperator("+")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"id":1450},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("1")","text":"1"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","range":{"startColumn":54,"endRow":114,"endColumn":55,"startRow":114},"id":1451,"parent":1446},{"type":"other","parent":1451,"text":"1","range":{"startRow":114,"startColumn":54,"endColumn":55,"endRow":114},"token":{"leadingTrivia":"","kind":"integerLiteral("1")","trailingTrivia":""},"structure":[],"id":1452},{"type":"other","parent":1427,"text":")","range":{"startRow":114,"startColumn":55,"endColumn":56,"endRow":114},"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"structure":[],"id":1453},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"name":"Count","value":{"text":"0"}}],"type":"collection","text":"MultipleTrailingClosureElementList","range":{"startRow":114,"startColumn":56,"endColumn":56,"endRow":114},"id":1454,"parent":1427},{"text":"CodeBlockItem","parent":1,"range":{"endColumn":14,"endRow":115,"startRow":115,"startColumn":1},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"item","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":1455,"type":"other"},{"text":"InfixOperatorExpr","parent":1455,"range":{"endRow":115,"startRow":115,"startColumn":1,"endColumn":14},"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"SubscriptCallExprSyntax","value":{"text":"SubscriptCallExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"AssignmentExprSyntax","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"id":1456,"type":"expr"},{"text":"SubscriptCallExpr","parent":1456,"range":{"startRow":115,"startColumn":1,"endColumn":10,"endRow":115},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftSquare"},{"value":{"text":"[","kind":"leftSquare"},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightSquareAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":1457,"type":"expr"},{"id":1458,"range":{"startColumn":1,"endColumn":6,"endRow":115,"startRow":115},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"board","kind":"identifier("board")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"text":"DeclReferenceExpr","parent":1457},{"type":"other","parent":1458,"text":"board","range":{"startColumn":1,"endRow":115,"startRow":115,"endColumn":6},"token":{"trailingTrivia":"","kind":"identifier("board")","leadingTrivia":"↲<\/span>"},"id":1459,"structure":[]},{"type":"other","parent":1457,"text":"[","range":{"startColumn":6,"startRow":115,"endRow":115,"endColumn":7},"token":{"trailingTrivia":"","kind":"leftSquare","leadingTrivia":""},"id":1460,"structure":[]},{"id":1461,"text":"LabeledExprList","type":"collection","range":{"startColumn":7,"startRow":115,"endRow":115,"endColumn":9},"parent":1457,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"id":1462,"text":"LabeledExpr","type":"other","range":{"endColumn":9,"startColumn":7,"endRow":115,"startRow":115},"parent":1461,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"id":1463,"text":"IntegerLiteralExpr","type":"expr","range":{"endColumn":9,"endRow":115,"startRow":115,"startColumn":7},"parent":1462,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"03","kind":"integerLiteral("03")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"type":"other","parent":1463,"text":"03","range":{"endColumn":9,"startColumn":7,"endRow":115,"startRow":115},"token":{"kind":"integerLiteral("03")","leadingTrivia":"","trailingTrivia":""},"structure":[],"id":1464},{"type":"other","parent":1457,"text":"]","range":{"endColumn":10,"startColumn":9,"endRow":115,"startRow":115},"token":{"kind":"rightSquare","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"id":1465},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","id":1466,"range":{"endColumn":11,"startColumn":11,"endRow":115,"startRow":115},"text":"MultipleTrailingClosureElementList","parent":1457},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"type":"expr","id":1467,"range":{"endColumn":12,"startColumn":11,"endRow":115,"startRow":115},"text":"AssignmentExpr","parent":1456},{"type":"other","parent":1467,"text":"=","range":{"endColumn":12,"startRow":115,"startColumn":11,"endRow":115},"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"id":1468},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"8","kind":"integerLiteral("8")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","id":1469,"range":{"endColumn":14,"startRow":115,"startColumn":13,"endRow":115},"text":"IntegerLiteralExpr","parent":1456},{"type":"other","parent":1469,"text":"8","range":{"endRow":115,"startRow":115,"startColumn":13,"endColumn":14},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("8")"},"structure":[],"id":1470},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","id":1471,"range":{"endRow":116,"startRow":116,"startColumn":1,"endColumn":15},"text":"CodeBlockItem","parent":1},{"type":"expr","text":"InfixOperatorExpr","id":1472,"range":{"endRow":116,"startRow":116,"startColumn":1,"endColumn":15},"parent":1471,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"SubscriptCallExprSyntax"},"name":"leftOperand","ref":"SubscriptCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"AssignmentExprSyntax"},"name":"operator","ref":"AssignmentExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}]},{"type":"expr","text":"SubscriptCallExpr","id":1473,"range":{"endRow":116,"startRow":116,"endColumn":10,"startColumn":1},"parent":1472,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"text":"[","kind":"leftSquare"}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightSquareAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"board","kind":"identifier("board")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"range":{"startRow":116,"endRow":116,"endColumn":6,"startColumn":1},"parent":1473,"type":"expr","id":1474,"text":"DeclReferenceExpr"},{"type":"other","parent":1474,"text":"board","range":{"endColumn":6,"startColumn":1,"endRow":116,"startRow":116},"token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>","kind":"identifier("board")"},"structure":[],"id":1475},{"type":"other","parent":1473,"text":"[","range":{"endColumn":7,"startColumn":6,"endRow":116,"startRow":116},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftSquare"},"structure":[],"id":1476},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"endColumn":9,"startColumn":7,"endRow":116,"startRow":116},"parent":1473,"type":"collection","id":1477,"text":"LabeledExprList"},{"id":1478,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","range":{"startColumn":7,"endColumn":9,"endRow":116,"startRow":116},"parent":1477,"text":"LabeledExpr"},{"id":1479,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"06","kind":"integerLiteral("06")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","range":{"endColumn":9,"endRow":116,"startColumn":7,"startRow":116},"parent":1478,"text":"IntegerLiteralExpr"},{"type":"other","parent":1479,"text":"06","range":{"endRow":116,"startColumn":7,"startRow":116,"endColumn":9},"token":{"trailingTrivia":"","kind":"integerLiteral("06")","leadingTrivia":""},"id":1480,"structure":[]},{"type":"other","parent":1473,"text":"]","range":{"endRow":116,"startColumn":9,"startRow":116,"endColumn":10},"token":{"trailingTrivia":"␣<\/span>","kind":"rightSquare","leadingTrivia":""},"id":1481,"structure":[]},{"text":"MultipleTrailingClosureElementList","parent":1473,"range":{"startRow":116,"endRow":116,"startColumn":11,"endColumn":11},"type":"collection","id":1482,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"text":"AssignmentExpr","parent":1472,"range":{"endColumn":12,"endRow":116,"startColumn":11,"startRow":116},"id":1483,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"type":"expr"},{"type":"other","parent":1483,"text":"=","range":{"endRow":116,"endColumn":12,"startRow":116,"startColumn":11},"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":1484,"structure":[]},{"text":"IntegerLiteralExpr","parent":1472,"range":{"endRow":116,"endColumn":15,"startRow":116,"startColumn":13},"id":1485,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"11","kind":"integerLiteral("11")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr"},{"type":"other","parent":1485,"text":"11","range":{"endColumn":15,"startRow":116,"startColumn":13,"endRow":116},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("11")"},"id":1486,"structure":[]},{"text":"CodeBlockItem","parent":1,"range":{"endColumn":14,"startRow":117,"startColumn":1,"endRow":117},"id":1487,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other"},{"text":"InfixOperatorExpr","parent":1487,"range":{"endRow":117,"endColumn":14,"startRow":117,"startColumn":1},"id":1488,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"SubscriptCallExprSyntax","value":{"text":"SubscriptCallExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"AssignmentExprSyntax","value":{"text":"AssignmentExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"type":"expr"},{"parent":1488,"range":{"endColumn":10,"startColumn":1,"endRow":117,"startRow":117},"id":1489,"text":"SubscriptCallExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftSquare"},{"value":{"text":"[","kind":"leftSquare"},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightSquare"},{"value":{"kind":"rightSquare","text":"]"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightSquareAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr"},{"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("board")","text":"board"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"startColumn":1,"endColumn":6,"startRow":117,"endRow":117},"parent":1489,"type":"expr","id":1490},{"type":"other","parent":1490,"text":"board","range":{"endRow":117,"endColumn":6,"startColumn":1,"startRow":117},"token":{"trailingTrivia":"","kind":"identifier("board")","leadingTrivia":"↲<\/span>"},"structure":[],"id":1491},{"type":"other","parent":1489,"text":"[","range":{"endRow":117,"endColumn":7,"startColumn":6,"startRow":117},"token":{"trailingTrivia":"","kind":"leftSquare","leadingTrivia":""},"structure":[],"id":1492},{"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"endRow":117,"endColumn":9,"startColumn":7,"startRow":117},"parent":1489,"type":"collection","id":1493},{"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"startRow":117,"startColumn":7,"endColumn":9,"endRow":117},"parent":1493,"type":"other","id":1494},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("09")","text":"09"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"range":{"endRow":117,"startRow":117,"endColumn":9,"startColumn":7},"type":"expr","text":"IntegerLiteralExpr","parent":1494,"id":1495},{"type":"other","parent":1495,"text":"09","range":{"endRow":117,"endColumn":9,"startRow":117,"startColumn":7},"token":{"kind":"integerLiteral("09")","trailingTrivia":"","leadingTrivia":""},"structure":[],"id":1496},{"type":"other","parent":1489,"text":"]","range":{"endRow":117,"endColumn":10,"startRow":117,"startColumn":9},"token":{"kind":"rightSquare","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"id":1497},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"range":{"endRow":117,"endColumn":11,"startRow":117,"startColumn":11},"type":"collection","text":"MultipleTrailingClosureElementList","parent":1489,"id":1498},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"range":{"endRow":117,"endColumn":12,"startRow":117,"startColumn":11},"type":"expr","text":"AssignmentExpr","parent":1488,"id":1499},{"range":{"endRow":117,"startColumn":11,"endColumn":12,"startRow":117},"parent":1499,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"id":1500,"structure":[],"type":"other","text":"="},{"id":1501,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"kind":"integerLiteral("9")","text":"9"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","range":{"endRow":117,"startColumn":13,"endColumn":14,"startRow":117},"parent":1488},{"range":{"startRow":117,"startColumn":13,"endRow":117,"endColumn":14},"parent":1501,"token":{"kind":"integerLiteral("9")","leadingTrivia":"","trailingTrivia":""},"id":1502,"structure":[],"type":"other","text":"9"},{"id":1503,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","range":{"startRow":118,"startColumn":1,"endRow":118,"endColumn":14},"parent":1},{"id":1504,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"SubscriptCallExprSyntax"},"ref":"SubscriptCallExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"AssignmentExprSyntax"},"ref":"AssignmentExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"rightOperand","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","text":"InfixOperatorExpr","range":{"startColumn":1,"endRow":118,"endColumn":14,"startRow":118},"parent":1503},{"parent":1504,"text":"SubscriptCallExpr","range":{"endColumn":10,"startRow":118,"startColumn":1,"endRow":118},"type":"expr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"kind":"leftSquare","text":"["}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"text":"]","kind":"rightSquare"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":1505},{"parent":1505,"text":"DeclReferenceExpr","range":{"startRow":118,"endRow":118,"startColumn":1,"endColumn":6},"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"board","kind":"identifier("board")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1506},{"range":{"startColumn":1,"endRow":118,"endColumn":6,"startRow":118},"parent":1506,"token":{"kind":"identifier("board")","leadingTrivia":"↲<\/span>","trailingTrivia":""},"structure":[],"type":"other","text":"board","id":1507},{"range":{"startColumn":6,"endRow":118,"endColumn":7,"startRow":118},"parent":1505,"token":{"kind":"leftSquare","leadingTrivia":"","trailingTrivia":""},"structure":[],"type":"other","text":"[","id":1508},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","parent":1505,"text":"LabeledExprList","range":{"startColumn":7,"endRow":118,"endColumn":9,"startRow":118},"id":1509},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","parent":1509,"text":"LabeledExpr","range":{"startColumn":7,"endRow":118,"endColumn":9,"startRow":118},"id":1510},{"text":"IntegerLiteralExpr","parent":1510,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"10","kind":"integerLiteral("10")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"endColumn":9,"endRow":118,"startRow":118,"startColumn":7},"type":"expr","id":1511},{"range":{"startRow":118,"endColumn":9,"startColumn":7,"endRow":118},"parent":1511,"token":{"kind":"integerLiteral("10")","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"10","type":"other","id":1512},{"range":{"startRow":118,"endColumn":10,"startColumn":9,"endRow":118},"parent":1505,"token":{"kind":"rightSquare","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"text":"]","type":"other","id":1513},{"text":"MultipleTrailingClosureElementList","parent":1505,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"range":{"startRow":118,"endColumn":11,"startColumn":11,"endRow":118},"type":"collection","id":1514},{"text":"AssignmentExpr","parent":1504,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"range":{"endRow":118,"startRow":118,"startColumn":11,"endColumn":12},"type":"expr","id":1515},{"range":{"startColumn":11,"endRow":118,"startRow":118,"endColumn":12},"parent":1515,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"equal"},"structure":[],"text":"=","type":"other","id":1516},{"parent":1504,"id":1517,"text":"IntegerLiteralExpr","type":"expr","range":{"startColumn":13,"endColumn":14,"endRow":118,"startRow":118},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"2","kind":"integerLiteral("2")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}]},{"range":{"startColumn":13,"endRow":118,"endColumn":14,"startRow":118},"parent":1517,"token":{"leadingTrivia":"","kind":"integerLiteral("2")","trailingTrivia":""},"id":1518,"text":"2","type":"other","structure":[]},{"text":"CodeBlockItem","range":{"startColumn":1,"endRow":119,"endColumn":16,"startRow":119},"type":"other","id":1519,"parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"text":"InfixOperatorExpr","range":{"startColumn":1,"endRow":119,"endColumn":16,"startRow":119},"type":"expr","id":1520,"parent":1519,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"SubscriptCallExprSyntax","name":"leftOperand","value":{"text":"SubscriptCallExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"PrefixOperatorExprSyntax","name":"rightOperand","value":{"text":"PrefixOperatorExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}]},{"text":"SubscriptCallExpr","range":{"endRow":119,"endColumn":10,"startRow":119,"startColumn":1},"type":"expr","id":1521,"parent":1520,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"text":"[","kind":"leftSquare"}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"type":"expr","id":1522,"parent":1521,"range":{"startRow":119,"endRow":119,"endColumn":6,"startColumn":1},"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"board","kind":"identifier("board")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"range":{"endColumn":6,"endRow":119,"startRow":119,"startColumn":1},"parent":1522,"token":{"kind":"identifier("board")","trailingTrivia":"","leadingTrivia":"↲<\/span>"},"structure":[],"text":"board","type":"other","id":1523},{"range":{"endColumn":7,"endRow":119,"startRow":119,"startColumn":6},"parent":1521,"token":{"kind":"leftSquare","trailingTrivia":"","leadingTrivia":""},"structure":[],"text":"[","type":"other","id":1524},{"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","id":1525,"parent":1521,"range":{"endColumn":9,"endRow":119,"startRow":119,"startColumn":7}},{"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"expression","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":1526,"parent":1525,"range":{"startRow":119,"endRow":119,"startColumn":7,"endColumn":9}},{"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"14","kind":"integerLiteral("14")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","id":1527,"parent":1526,"range":{"endRow":119,"startColumn":7,"startRow":119,"endColumn":9}},{"range":{"endRow":119,"startRow":119,"startColumn":7,"endColumn":9},"parent":1527,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("14")"},"structure":[],"id":1528,"text":"14","type":"other"},{"range":{"endRow":119,"startRow":119,"startColumn":9,"endColumn":10},"parent":1521,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightSquare"},"structure":[],"id":1529,"text":"]","type":"other"},{"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":1521,"id":1530,"text":"MultipleTrailingClosureElementList","range":{"endRow":119,"startRow":119,"startColumn":11,"endColumn":11},"type":"collection"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"parent":1520,"id":1531,"text":"AssignmentExpr","range":{"startRow":119,"endRow":119,"startColumn":11,"endColumn":12},"type":"expr"},{"range":{"startRow":119,"endRow":119,"startColumn":11,"endColumn":12},"parent":1531,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"equal"},"structure":[],"id":1532,"text":"=","type":"other"},{"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"-","kind":"prefixOperator("-")"}},{"name":"unexpectedBetweenOperatorAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"parent":1520,"id":1533,"text":"PrefixOperatorExpr","range":{"startRow":119,"endRow":119,"startColumn":13,"endColumn":16},"type":"expr"},{"range":{"endRow":119,"endColumn":14,"startRow":119,"startColumn":13},"parent":1533,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"prefixOperator("-")"},"structure":[],"type":"other","text":"-","id":1534},{"type":"expr","text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("10")","text":"10"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":1535,"parent":1533,"range":{"endRow":119,"endColumn":16,"startRow":119,"startColumn":14}},{"range":{"startRow":119,"endColumn":16,"startColumn":14,"endRow":119},"parent":1535,"token":{"trailingTrivia":"","kind":"integerLiteral("10")","leadingTrivia":""},"structure":[],"type":"other","text":"10","id":1536},{"type":"other","text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"item","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":1537,"parent":1,"range":{"startRow":120,"endColumn":16,"startColumn":1,"endRow":120}},{"type":"expr","text":"InfixOperatorExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"SubscriptCallExprSyntax"},"name":"leftOperand","ref":"SubscriptCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"AssignmentExprSyntax"},"name":"operator","ref":"AssignmentExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"PrefixOperatorExprSyntax"},"ref":"PrefixOperatorExprSyntax","name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"id":1538,"parent":1537,"range":{"startRow":120,"endColumn":16,"startColumn":1,"endRow":120}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftSquare"},{"value":{"kind":"leftSquare","text":"["},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightSquare"},{"value":{"kind":"rightSquare","text":"]"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightSquareAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":1539,"text":"SubscriptCallExpr","parent":1538,"range":{"startColumn":1,"endColumn":10,"startRow":120,"endRow":120},"type":"expr"},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"board","kind":"identifier("board")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1540,"text":"DeclReferenceExpr","parent":1539,"range":{"endColumn":6,"endRow":120,"startRow":120,"startColumn":1},"type":"expr"},{"range":{"startRow":120,"endColumn":6,"startColumn":1,"endRow":120},"parent":1540,"token":{"leadingTrivia":"↲<\/span>","kind":"identifier("board")","trailingTrivia":""},"id":1541,"text":"board","type":"other","structure":[]},{"range":{"startRow":120,"endColumn":7,"startColumn":6,"endRow":120},"parent":1539,"token":{"leadingTrivia":"","kind":"leftSquare","trailingTrivia":""},"id":1542,"text":"[","type":"other","structure":[]},{"id":1543,"parent":1539,"text":"LabeledExprList","type":"collection","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"startRow":120,"endColumn":9,"startColumn":7,"endRow":120}},{"id":1544,"parent":1543,"text":"LabeledExpr","type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endColumn":9,"endRow":120,"startColumn":7,"startRow":120}},{"parent":1544,"text":"IntegerLiteralExpr","range":{"endRow":120,"endColumn":9,"startColumn":7,"startRow":120},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"19","kind":"integerLiteral("19")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","id":1545},{"range":{"endColumn":9,"startColumn":7,"startRow":120,"endRow":120},"parent":1545,"token":{"kind":"integerLiteral("19")","trailingTrivia":"","leadingTrivia":""},"structure":[],"text":"19","type":"other","id":1546},{"range":{"endColumn":10,"startColumn":9,"startRow":120,"endRow":120},"parent":1539,"token":{"kind":"rightSquare","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"text":"]","type":"other","id":1547},{"parent":1539,"text":"MultipleTrailingClosureElementList","range":{"endColumn":11,"startColumn":11,"startRow":120,"endRow":120},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","id":1548},{"parent":1538,"text":"AssignmentExpr","range":{"endRow":120,"startColumn":11,"startRow":120,"endColumn":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"type":"expr","id":1549},{"range":{"startColumn":11,"endColumn":12,"startRow":120,"endRow":120},"parent":1549,"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"text":"=","type":"other","id":1550},{"parent":1538,"text":"PrefixOperatorExpr","range":{"startColumn":13,"endColumn":16,"startRow":120,"endRow":120},"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"-","kind":"prefixOperator("-")"}},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"expr","id":1551},{"range":{"endRow":120,"endColumn":14,"startRow":120,"startColumn":13},"parent":1551,"token":{"trailingTrivia":"","kind":"prefixOperator("-")","leadingTrivia":""},"id":1552,"text":"-","structure":[],"type":"other"},{"range":{"endRow":120,"endColumn":16,"startRow":120,"startColumn":14},"parent":1551,"text":"IntegerLiteralExpr","id":1553,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"11","kind":"integerLiteral("11")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr"},{"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("11")"},"parent":1553,"text":"11","structure":[],"range":{"startRow":120,"endRow":120,"startColumn":14,"endColumn":16},"id":1554},{"range":{"startRow":121,"endRow":121,"startColumn":1,"endColumn":15},"parent":1,"text":"CodeBlockItem","id":1555,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"item","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other"},{"range":{"startRow":121,"startColumn":1,"endColumn":15,"endRow":121},"parent":1555,"text":"InfixOperatorExpr","id":1556,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"SubscriptCallExprSyntax","value":{"text":"SubscriptCallExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"PrefixOperatorExprSyntax","name":"rightOperand","value":{"text":"PrefixOperatorExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr"},{"type":"expr","id":1557,"parent":1556,"text":"SubscriptCallExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftSquare"},{"value":{"text":"[","kind":"leftSquare"},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightSquare"},{"value":{"kind":"rightSquare","text":"]"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightSquareAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"range":{"startRow":121,"startColumn":1,"endColumn":10,"endRow":121}},{"text":"DeclReferenceExpr","type":"expr","range":{"endColumn":6,"startRow":121,"endRow":121,"startColumn":1},"id":1558,"parent":1557,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"board","kind":"identifier("board")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","token":{"trailingTrivia":"","kind":"identifier("board")","leadingTrivia":"↲<\/span>"},"text":"board","parent":1558,"structure":[],"range":{"startRow":121,"endColumn":6,"startColumn":1,"endRow":121},"id":1559},{"type":"other","token":{"trailingTrivia":"","kind":"leftSquare","leadingTrivia":""},"text":"[","parent":1557,"structure":[],"range":{"startRow":121,"endColumn":7,"startColumn":6,"endRow":121},"id":1560},{"text":"LabeledExprList","type":"collection","range":{"startRow":121,"endColumn":9,"startColumn":7,"endRow":121},"id":1561,"parent":1557,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"text":"LabeledExpr","type":"other","range":{"startColumn":7,"endColumn":9,"endRow":121,"startRow":121},"id":1562,"parent":1561,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"text":"IntegerLiteralExpr","range":{"endRow":121,"endColumn":9,"startColumn":7,"startRow":121},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"22","kind":"integerLiteral("22")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","id":1563,"parent":1562},{"type":"other","token":{"kind":"integerLiteral("22")","trailingTrivia":"","leadingTrivia":""},"text":"22","parent":1563,"structure":[],"range":{"startRow":121,"endRow":121,"endColumn":9,"startColumn":7},"id":1564},{"type":"other","token":{"kind":"rightSquare","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":"]","parent":1557,"structure":[],"range":{"startRow":121,"endRow":121,"endColumn":10,"startColumn":9},"id":1565},{"text":"MultipleTrailingClosureElementList","range":{"startRow":121,"endRow":121,"endColumn":11,"startColumn":11},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","id":1566,"parent":1557},{"text":"AssignmentExpr","range":{"endRow":121,"endColumn":12,"startColumn":11,"startRow":121},"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"type":"expr","id":1567,"parent":1556},{"type":"other","token":{"leadingTrivia":"","kind":"equal","trailingTrivia":"␣<\/span>"},"text":"=","parent":1567,"structure":[],"range":{"endColumn":12,"startRow":121,"startColumn":11,"endRow":121},"id":1568},{"id":1569,"parent":1556,"type":"expr","range":{"endRow":121,"endColumn":15,"startColumn":13,"startRow":121},"text":"PrefixOperatorExpr","structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"prefixOperator("-")","text":"-"}},{"name":"unexpectedBetweenOperatorAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"type":"other","token":{"leadingTrivia":"","kind":"prefixOperator("-")","trailingTrivia":""},"parent":1569,"text":"-","structure":[],"range":{"startColumn":13,"startRow":121,"endRow":121,"endColumn":14},"id":1570},{"id":1571,"parent":1569,"type":"expr","range":{"startColumn":14,"startRow":121,"endRow":121,"endColumn":15},"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("2")","text":"2"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"type":"other","token":{"leadingTrivia":"","kind":"integerLiteral("2")","trailingTrivia":""},"parent":1571,"text":"2","structure":[],"range":{"startRow":121,"startColumn":14,"endRow":121,"endColumn":15},"id":1572},{"id":1573,"parent":1,"type":"other","range":{"startRow":122,"startColumn":1,"endRow":122,"endColumn":15},"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"id":1574,"parent":1573,"type":"expr","text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"SubscriptCallExprSyntax","name":"leftOperand","value":{"text":"SubscriptCallExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"PrefixOperatorExprSyntax","name":"rightOperand","value":{"text":"PrefixOperatorExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"range":{"startColumn":1,"endRow":122,"endColumn":15,"startRow":122}},{"id":1575,"parent":1574,"type":"expr","text":"SubscriptCallExpr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"text":"[","kind":"leftSquare"}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"range":{"endColumn":10,"startRow":122,"startColumn":1,"endRow":122}},{"text":"DeclReferenceExpr","range":{"startColumn":1,"startRow":122,"endColumn":6,"endRow":122},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"board","kind":"identifier("board")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","id":1576,"parent":1575},{"type":"other","token":{"leadingTrivia":"↲<\/span>","kind":"identifier("board")","trailingTrivia":""},"text":"board","parent":1576,"structure":[],"range":{"startColumn":1,"startRow":122,"endRow":122,"endColumn":6},"id":1577},{"type":"other","token":{"leadingTrivia":"","kind":"leftSquare","trailingTrivia":""},"text":"[","parent":1575,"structure":[],"range":{"startColumn":6,"startRow":122,"endRow":122,"endColumn":7},"id":1578},{"text":"LabeledExprList","range":{"startColumn":7,"startRow":122,"endRow":122,"endColumn":9},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","id":1579,"parent":1575},{"text":"LabeledExpr","range":{"startColumn":7,"endColumn":9,"endRow":122,"startRow":122},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":1580,"parent":1579},{"type":"expr","range":{"endColumn":9,"startColumn":7,"startRow":122,"endRow":122},"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"24","kind":"integerLiteral("24")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":1581,"parent":1580},{"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("24")"},"text":"24","parent":1581,"structure":[],"range":{"startColumn":7,"startRow":122,"endColumn":9,"endRow":122},"id":1582},{"type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"rightSquare"},"text":"]","parent":1575,"structure":[],"range":{"startColumn":9,"startRow":122,"endColumn":10,"endRow":122},"id":1583},{"type":"collection","range":{"startColumn":11,"startRow":122,"endColumn":11,"endRow":122},"text":"MultipleTrailingClosureElementList","structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":1584,"parent":1575},{"type":"expr","range":{"endColumn":12,"endRow":122,"startRow":122,"startColumn":11},"text":"AssignmentExpr","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"id":1585,"parent":1574},{"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"text":"=","parent":1585,"structure":[],"range":{"endRow":122,"startColumn":11,"endColumn":12,"startRow":122},"id":1586},{"text":"PrefixOperatorExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"prefixOperator("-")","text":"-"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"range":{"endRow":122,"startColumn":13,"endColumn":15,"startRow":122},"type":"expr","parent":1574,"id":1587},{"type":"other","token":{"kind":"prefixOperator("-")","trailingTrivia":"","leadingTrivia":""},"text":"-","parent":1587,"structure":[],"range":{"endColumn":14,"startColumn":13,"endRow":122,"startRow":122},"id":1588},{"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("8")","text":"8"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"endColumn":15,"startColumn":14,"endRow":122,"startRow":122},"type":"expr","parent":1587,"id":1589},{"type":"other","token":{"kind":"integerLiteral("8")","leadingTrivia":"","trailingTrivia":""},"text":"8","parent":1589,"structure":[],"range":{"startRow":122,"endColumn":15,"endRow":122,"startColumn":14},"id":1590},{"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"range":{"startRow":124,"endColumn":15,"endRow":124,"startColumn":1},"type":"other","parent":1,"id":1591},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"type":"decl","id":1592,"text":"VariableDecl","parent":1591,"range":{"endRow":124,"endColumn":15,"startRow":124,"startColumn":1}},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","id":1593,"text":"AttributeList","parent":1592,"range":{"endColumn":15,"startColumn":15,"startRow":122,"endRow":122}},{"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","id":1594,"text":"DeclModifierList","parent":1592,"range":{"startColumn":15,"startRow":122,"endColumn":15,"endRow":122}},{"type":"other","token":{"leadingTrivia":"↲<\/span>↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)","trailingTrivia":"␣<\/span>"},"parent":1592,"text":"var","structure":[],"range":{"startColumn":1,"endRow":124,"startRow":124,"endColumn":4},"id":1595},{"parent":1592,"id":1596,"text":"PatternBindingList","structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","range":{"startColumn":5,"endRow":124,"startRow":124,"endColumn":15}},{"parent":1596,"id":1597,"text":"PatternBinding","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","range":{"startRow":124,"startColumn":5,"endRow":124,"endColumn":15}},{"parent":1597,"id":1598,"text":"IdentifierPattern","structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"square","kind":"identifier("square")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"type":"pattern","range":{"endRow":124,"startColumn":5,"startRow":124,"endColumn":11}},{"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("square")"},"parent":1598,"text":"square","structure":[],"range":{"endRow":124,"startColumn":5,"endColumn":11,"startRow":124},"id":1599},{"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"parent":1597,"type":"other","id":1600,"range":{"endRow":124,"startColumn":12,"endColumn":15,"startRow":124},"text":"InitializerClause"},{"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"parent":1600,"text":"=","structure":[],"range":{"startRow":124,"endColumn":13,"startColumn":12,"endRow":124},"id":1601},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"0","kind":"integerLiteral("0")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":1600,"type":"expr","id":1602,"range":{"startRow":124,"endColumn":15,"startColumn":14,"endRow":124},"text":"IntegerLiteralExpr"},{"type":"other","token":{"kind":"integerLiteral("0")","leadingTrivia":"","trailingTrivia":""},"parent":1602,"text":"0","structure":[],"range":{"startColumn":14,"endColumn":15,"startRow":124,"endRow":124},"id":1603},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"VariableDeclSyntax","name":"item","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":1,"type":"other","id":1604,"range":{"startColumn":1,"endColumn":17,"startRow":125,"endRow":125},"text":"CodeBlockItem"},{"parent":1604,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.var)","text":"var"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"text":"VariableDecl","range":{"endRow":125,"startColumn":1,"endColumn":17,"startRow":125},"id":1605,"type":"decl"},{"parent":1605,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"text":"AttributeList","range":{"startColumn":15,"startRow":124,"endRow":124,"endColumn":15},"id":1606,"type":"collection"},{"parent":1605,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"text":"DeclModifierList","range":{"endColumn":15,"startColumn":15,"startRow":124,"endRow":124},"id":1607,"type":"collection"},{"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)","leadingTrivia":"↲<\/span>"},"text":"var","parent":1605,"structure":[],"range":{"endColumn":4,"endRow":125,"startRow":125,"startColumn":1},"id":1608},{"text":"PatternBindingList","parent":1605,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":1609,"range":{"endColumn":17,"endRow":125,"startRow":125,"startColumn":5}},{"text":"PatternBinding","parent":1609,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","id":1610,"range":{"startRow":125,"endRow":125,"startColumn":5,"endColumn":17}},{"id":1611,"parent":1610,"text":"IdentifierPattern","range":{"endColumn":13,"startColumn":5,"startRow":125,"endRow":125},"type":"pattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("diceRoll")","text":"diceRoll"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}]},{"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("diceRoll")","leadingTrivia":""},"parent":1611,"text":"diceRoll","structure":[],"range":{"startRow":125,"endColumn":13,"endRow":125,"startColumn":5},"id":1612},{"id":1613,"parent":1610,"text":"InitializerClause","range":{"startRow":125,"endColumn":17,"endRow":125,"startColumn":14},"type":"other","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"parent":1613,"text":"=","structure":[],"range":{"endColumn":15,"startColumn":14,"startRow":125,"endRow":125},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"id":1614,"type":"other"},{"id":1615,"parent":1613,"text":"IntegerLiteralExpr","range":{"endColumn":17,"startColumn":16,"startRow":125,"endRow":125},"type":"expr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"parent":1615,"text":"0","structure":[],"range":{"endColumn":17,"startRow":125,"startColumn":16,"endRow":125},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("0")"},"id":1616,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"WhileStmtSyntax"},"name":"item","ref":"WhileStmtSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","range":{"startRow":126,"endColumn":2,"endRow":138,"startColumn":1},"id":1617,"parent":1,"text":"CodeBlockItem"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeWhileKeyword"},{"value":{"text":"while","kind":"keyword(SwiftSyntax.Keyword.while)"},"name":"whileKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhileKeywordAndConditions"},{"value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax","name":"conditions"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionsAndBody"},{"value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax","name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"type":"other","range":{"endRow":138,"startRow":126,"endColumn":2,"startColumn":1},"id":1618,"parent":1617,"text":"WhileStmt"},{"parent":1618,"structure":[],"text":"while","range":{"endRow":126,"startRow":126,"startColumn":1,"endColumn":6},"token":{"kind":"keyword(SwiftSyntax.Keyword.while)","leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>"},"id":1619,"type":"other"},{"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","range":{"endRow":126,"startRow":126,"startColumn":7,"endColumn":28},"id":1620,"parent":1618,"text":"ConditionElementList"},{"structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"name":"condition","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenConditionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","range":{"startRow":126,"startColumn":7,"endRow":126,"endColumn":28},"id":1621,"parent":1620,"text":"ConditionElement"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"parent":1621,"id":1622,"text":"InfixOperatorExpr","range":{"endRow":126,"endColumn":28,"startRow":126,"startColumn":7},"type":"expr"},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("square")","text":"square"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":1622,"id":1623,"text":"DeclReferenceExpr","range":{"startRow":126,"endColumn":13,"endRow":126,"startColumn":7},"type":"expr"},{"parent":1623,"structure":[],"text":"square","range":{"endColumn":13,"startColumn":7,"startRow":126,"endRow":126},"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("square")","leadingTrivia":""},"id":1624,"type":"other"},{"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("!=")","text":"!="}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"range":{"endColumn":16,"startColumn":14,"startRow":126,"endRow":126},"parent":1622,"text":"BinaryOperatorExpr","id":1625,"type":"expr"},{"parent":1625,"structure":[],"text":"!=","range":{"startRow":126,"endColumn":16,"startColumn":14,"endRow":126},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"binaryOperator("!=")"},"id":1626,"type":"other"},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("finalSquare")","text":"finalSquare"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"startRow":126,"endColumn":28,"startColumn":17,"endRow":126},"parent":1622,"text":"DeclReferenceExpr","id":1627,"type":"expr"},{"parent":1627,"structure":[],"text":"finalSquare","range":{"startRow":126,"startColumn":17,"endColumn":28,"endRow":126},"token":{"leadingTrivia":"","kind":"identifier("finalSquare")","trailingTrivia":"␣<\/span>"},"id":1628,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"range":{"startRow":126,"startColumn":29,"endColumn":2,"endRow":138},"parent":1618,"text":"CodeBlock","id":1629,"type":"other"},{"parent":1629,"structure":[],"text":"{","range":{"startColumn":29,"endColumn":30,"startRow":126,"endRow":126},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"id":1630,"type":"other"},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"text":"CodeBlockItemList","id":1631,"parent":1629,"range":{"startColumn":5,"endColumn":6,"startRow":127,"endRow":137},"type":"collection"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"text":"CodeBlockItem","id":1632,"parent":1631,"range":{"startColumn":5,"endRow":127,"startRow":127,"endColumn":18},"type":"other"},{"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"BinaryOperatorExprSyntax","name":"operator","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"rightOperand","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"text":"InfixOperatorExpr","id":1633,"parent":1632,"range":{"startRow":127,"endRow":127,"endColumn":18,"startColumn":5},"type":"expr"},{"type":"expr","id":1634,"range":{"endRow":127,"endColumn":13,"startRow":127,"startColumn":5},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"diceRoll","kind":"identifier("diceRoll")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","parent":1633},{"parent":1634,"structure":[],"text":"diceRoll","range":{"endRow":127,"startColumn":5,"startRow":127,"endColumn":13},"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("diceRoll")"},"id":1635,"type":"other"},{"type":"expr","id":1636,"range":{"endRow":127,"startColumn":14,"startRow":127,"endColumn":16},"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"+=","kind":"binaryOperator("+=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"text":"BinaryOperatorExpr","parent":1633},{"parent":1636,"structure":[],"text":"+=","range":{"startRow":127,"endColumn":16,"startColumn":14,"endRow":127},"token":{"kind":"binaryOperator("+=")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"id":1637,"type":"other"},{"range":{"startRow":127,"startColumn":17,"endRow":127,"endColumn":18},"parent":1633,"text":"IntegerLiteralExpr","type":"expr","id":1638,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"name":"literal","value":{"text":"1","kind":"integerLiteral("1")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"parent":1638,"structure":[],"text":"1","range":{"endColumn":18,"startRow":127,"startColumn":17,"endRow":127},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("1")"},"id":1639,"type":"other"},{"id":1640,"range":{"endColumn":38,"startRow":128,"startColumn":5,"endRow":128},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ExpressionStmtSyntax"},"name":"item","ref":"ExpressionStmtSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"text":"CodeBlockItem","parent":1631,"type":"other"},{"id":1641,"range":{"endColumn":38,"startColumn":5,"endRow":128,"startRow":128},"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IfExprSyntax"},"ref":"IfExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"text":"ExpressionStmt","parent":1640,"type":"other"},{"id":1642,"range":{"endColumn":38,"startRow":128,"endRow":128,"startColumn":5},"structure":[{"name":"unexpectedBeforeIfKeyword","value":{"text":"nil"}},{"name":"ifKeyword","value":{"text":"if","kind":"keyword(SwiftSyntax.Keyword.if)"}},{"name":"unexpectedBetweenIfKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","ref":"ConditionElementListSyntax","value":{"text":"ConditionElementListSyntax"}},{"name":"unexpectedBetweenConditionsAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedBetweenBodyAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenElseKeywordAndElseBody","value":{"text":"nil"}},{"name":"elseBody","value":{"text":"nil"}},{"name":"unexpectedAfterElseBody","value":{"text":"nil"}}],"text":"IfExpr","parent":1641,"type":"expr"},{"parent":1642,"text":"if","structure":[],"range":{"startColumn":5,"endColumn":7,"startRow":128,"endRow":128},"token":{"kind":"keyword(SwiftSyntax.Keyword.if)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"id":1643,"type":"other"},{"parent":1642,"text":"ConditionElementList","structure":[{"value":{"text":"ConditionElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":1644,"range":{"startColumn":8,"endColumn":21,"startRow":128,"endRow":128},"type":"collection"},{"parent":1644,"text":"ConditionElement","structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"name":"condition","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenConditionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":1645,"range":{"endColumn":21,"startColumn":8,"startRow":128,"endRow":128},"type":"other"},{"parent":1645,"text":"InfixOperatorExpr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"id":1646,"range":{"startColumn":8,"endRow":128,"startRow":128,"endColumn":21},"type":"expr"},{"id":1647,"parent":1646,"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"diceRoll","kind":"identifier("diceRoll")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","range":{"endColumn":16,"startRow":128,"startColumn":8,"endRow":128}},{"parent":1647,"text":"diceRoll","structure":[],"range":{"endColumn":16,"endRow":128,"startRow":128,"startColumn":8},"token":{"kind":"identifier("diceRoll")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":1648,"type":"other"},{"id":1649,"parent":1646,"text":"BinaryOperatorExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator("==")","text":"=="},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"type":"expr","range":{"endColumn":19,"endRow":128,"startRow":128,"startColumn":17}},{"parent":1649,"text":"==","structure":[],"range":{"startColumn":17,"startRow":128,"endRow":128,"endColumn":19},"token":{"trailingTrivia":"␣<\/span>","kind":"binaryOperator("==")","leadingTrivia":""},"id":1650,"type":"other"},{"text":"IntegerLiteralExpr","parent":1646,"id":1651,"type":"expr","range":{"startColumn":20,"startRow":128,"endRow":128,"endColumn":21},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("7")","text":"7"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"parent":1651,"text":"7","structure":[],"range":{"endColumn":21,"endRow":128,"startColumn":20,"startRow":128},"token":{"kind":"integerLiteral("7")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"id":1652,"type":"other"},{"text":"CodeBlock","parent":1642,"id":1653,"type":"other","range":{"endColumn":38,"endRow":128,"startColumn":22,"startRow":128},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"parent":1653,"text":"{","structure":[],"range":{"endRow":128,"startColumn":22,"startRow":128,"endColumn":23},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"leftBrace"},"id":1654,"type":"other"},{"text":"CodeBlockItemList","parent":1653,"id":1655,"type":"collection","range":{"endRow":128,"startColumn":24,"startRow":128,"endColumn":36},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"id":1656,"text":"CodeBlockItem","range":{"startRow":128,"endRow":128,"startColumn":24,"endColumn":36},"parent":1655,"type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"InfixOperatorExprSyntax","name":"item","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"id":1657,"text":"InfixOperatorExpr","range":{"startColumn":24,"startRow":128,"endRow":128,"endColumn":36},"parent":1656,"type":"expr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"ref":"AssignmentExprSyntax","name":"operator","value":{"text":"AssignmentExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"rightOperand","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}]},{"id":1658,"text":"DeclReferenceExpr","range":{"startColumn":24,"endRow":128,"endColumn":32,"startRow":128},"parent":1657,"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"diceRoll","kind":"identifier("diceRoll")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"parent":1658,"structure":[],"text":"diceRoll","range":{"endRow":128,"startColumn":24,"startRow":128,"endColumn":32},"token":{"leadingTrivia":"","kind":"identifier("diceRoll")","trailingTrivia":"␣<\/span>"},"id":1659,"type":"other"},{"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"type":"expr","range":{"endRow":128,"startColumn":33,"startRow":128,"endColumn":34},"id":1660,"text":"AssignmentExpr","parent":1657},{"parent":1660,"structure":[],"text":"=","range":{"endColumn":34,"startRow":128,"endRow":128,"startColumn":33},"token":{"leadingTrivia":"","kind":"equal","trailingTrivia":"␣<\/span>"},"id":1661,"type":"other"},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("1")","text":"1"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","range":{"endColumn":36,"startRow":128,"endRow":128,"startColumn":35},"id":1662,"text":"IntegerLiteralExpr","parent":1657},{"parent":1662,"structure":[],"text":"1","range":{"endRow":128,"endColumn":36,"startRow":128,"startColumn":35},"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"integerLiteral("1")"},"id":1663,"type":"other"},{"parent":1653,"structure":[],"text":"}","range":{"endRow":128,"endColumn":38,"startRow":128,"startColumn":37},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightBrace"},"id":1664,"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ExpressionStmtSyntax"},"name":"item","ref":"ExpressionStmtSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","range":{"endRow":137,"endColumn":6,"startRow":129,"startColumn":5},"id":1665,"text":"CodeBlockItem","parent":1631},{"id":1666,"parent":1665,"text":"ExpressionStmt","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"SwitchExprSyntax","value":{"text":"SwitchExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"type":"other","range":{"startColumn":5,"endColumn":6,"startRow":129,"endRow":137}},{"id":1667,"parent":1666,"text":"SwitchExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeSwitchKeyword"},{"value":{"text":"switch","kind":"keyword(SwiftSyntax.Keyword.switch)"},"name":"switchKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenSwitchKeywordAndSubject"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"subject"},{"value":{"text":"nil"},"name":"unexpectedBetweenSubjectAndLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndCases"},{"ref":"SwitchCaseListSyntax","value":{"text":"SwitchCaseListSyntax"},"name":"cases"},{"value":{"text":"nil"},"name":"unexpectedBetweenCasesAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"expr","range":{"endRow":137,"startColumn":5,"endColumn":6,"startRow":129}},{"parent":1667,"text":"switch","structure":[],"range":{"endColumn":11,"startColumn":5,"startRow":129,"endRow":129},"token":{"kind":"keyword(SwiftSyntax.Keyword.switch)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"id":1668,"type":"other"},{"text":"InfixOperatorExpr","type":"expr","structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"id":1669,"parent":1667,"range":{"endColumn":29,"startColumn":12,"startRow":129,"endRow":129}},{"text":"DeclReferenceExpr","type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"square","kind":"identifier("square")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":1670,"parent":1669,"range":{"endColumn":18,"startColumn":12,"endRow":129,"startRow":129}},{"parent":1670,"text":"square","structure":[],"range":{"endRow":129,"endColumn":18,"startRow":129,"startColumn":12},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("square")"},"id":1671,"type":"other"},{"text":"BinaryOperatorExpr","type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator("+")","text":"+"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"id":1672,"parent":1669,"range":{"startColumn":19,"endColumn":20,"startRow":129,"endRow":129}},{"structure":[],"token":{"kind":"binaryOperator("+")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"parent":1672,"id":1673,"range":{"startColumn":19,"endColumn":20,"startRow":129,"endRow":129},"text":"+","type":"other"},{"id":1674,"parent":1669,"text":"DeclReferenceExpr","range":{"startColumn":21,"endColumn":29,"startRow":129,"endRow":129},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("diceRoll")","text":"diceRoll"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"structure":[],"token":{"kind":"identifier("diceRoll")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":1674,"id":1675,"range":{"startRow":129,"startColumn":21,"endRow":129,"endColumn":29},"text":"diceRoll","type":"other"},{"structure":[],"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"parent":1667,"id":1676,"range":{"startRow":129,"startColumn":30,"endRow":129,"endColumn":31},"text":"{","type":"other"},{"id":1677,"parent":1667,"text":"SwitchCaseList","range":{"startRow":130,"startColumn":5,"endRow":136,"endColumn":32},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"type":"collection"},{"id":1678,"parent":1677,"text":"SwitchCase","range":{"startRow":130,"endColumn":14,"startColumn":5,"endRow":131},"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"value":{"text":"SwitchCaseLabelSyntax"},"name":"label","ref":"SwitchCaseLabelSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterStatements"}],"type":"other"},{"text":"SwitchCaseLabel","parent":1678,"type":"other","id":1679,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCaseKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndCaseItems"},{"value":{"text":"SwitchCaseItemListSyntax"},"ref":"SwitchCaseItemListSyntax","name":"caseItems"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseItemsAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedAfterColon"}],"range":{"startColumn":5,"endRow":130,"endColumn":22,"startRow":130}},{"structure":[],"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)"},"parent":1679,"id":1680,"range":{"endColumn":9,"startRow":130,"endRow":130,"startColumn":5},"text":"case","type":"other"},{"text":"SwitchCaseItemList","parent":1679,"type":"collection","id":1681,"structure":[{"value":{"text":"SwitchCaseItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"range":{"endColumn":21,"startRow":130,"endRow":130,"startColumn":10}},{"text":"SwitchCaseItem","parent":1681,"type":"other","id":1682,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"value":{"text":"ExpressionPatternSyntax"},"name":"pattern","ref":"ExpressionPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"startRow":130,"endColumn":21,"startColumn":10,"endRow":130}},{"text":"ExpressionPattern","type":"pattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"id":1683,"range":{"endRow":130,"startRow":130,"endColumn":21,"startColumn":10},"parent":1682},{"text":"DeclReferenceExpr","type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"finalSquare","kind":"identifier("finalSquare")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":1684,"range":{"endRow":130,"startRow":130,"endColumn":21,"startColumn":10},"parent":1683},{"structure":[],"token":{"kind":"identifier("finalSquare")","leadingTrivia":"","trailingTrivia":""},"parent":1684,"id":1685,"range":{"startColumn":10,"endColumn":21,"startRow":130,"endRow":130},"text":"finalSquare","type":"other"},{"structure":[],"token":{"kind":"colon","trailingTrivia":"","leadingTrivia":""},"parent":1679,"range":{"startRow":130,"endRow":130,"startColumn":21,"endColumn":22},"id":1686,"text":":","type":"other"},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","range":{"startRow":131,"endRow":131,"startColumn":9,"endColumn":14},"text":"CodeBlockItemList","parent":1678,"id":1687},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"BreakStmtSyntax"},"ref":"BreakStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","range":{"endRow":131,"startRow":131,"startColumn":9,"endColumn":14},"text":"CodeBlockItem","parent":1687,"id":1688},{"structure":[{"name":"unexpectedBeforeBreakKeyword","value":{"text":"nil"}},{"name":"breakKeyword","value":{"text":"break","kind":"keyword(SwiftSyntax.Keyword.break)"}},{"name":"unexpectedBetweenBreakKeywordAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedAfterLabel","value":{"text":"nil"}}],"type":"other","range":{"startColumn":9,"startRow":131,"endColumn":14,"endRow":131},"text":"BreakStmt","parent":1688,"id":1689},{"structure":[],"token":{"kind":"keyword(SwiftSyntax.Keyword.break)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":1689,"range":{"startColumn":9,"endRow":131,"startRow":131,"endColumn":14},"id":1690,"text":"break","type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttribute"},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","ref":"SwitchCaseLabelSyntax","value":{"text":"SwitchCaseLabelSyntax"}},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other","range":{"startColumn":5,"endRow":133,"startRow":132,"endColumn":17},"text":"SwitchCase","parent":1677,"id":1691},{"range":{"startColumn":5,"endColumn":54,"endRow":132,"startRow":132},"structure":[{"name":"unexpectedBeforeCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndCaseItems","value":{"text":"nil"}},{"name":"caseItems","value":{"text":"SwitchCaseItemListSyntax"},"ref":"SwitchCaseItemListSyntax"},{"name":"unexpectedBetweenCaseItemsAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"text":"SwitchCaseLabel","id":1692,"type":"other","parent":1691},{"structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":1692,"range":{"endColumn":9,"endRow":132,"startRow":132,"startColumn":5},"id":1693,"text":"case","type":"other"},{"range":{"endColumn":53,"endRow":132,"startRow":132,"startColumn":10},"structure":[{"value":{"text":"SwitchCaseItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"SwitchCaseItemList","id":1694,"type":"collection","parent":1692},{"parent":1694,"text":"SwitchCaseItem","range":{"endColumn":53,"startColumn":10,"startRow":132,"endRow":132},"id":1695,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ValueBindingPatternSyntax","name":"pattern","value":{"text":"ValueBindingPatternSyntax"}},{"name":"unexpectedBetweenPatternAndWhereClause","value":{"text":"nil"}},{"ref":"WhereClauseSyntax","name":"whereClause","value":{"text":"WhereClauseSyntax"}},{"name":"unexpectedBetweenWhereClauseAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"parent":1695,"text":"ValueBindingPattern","range":{"startRow":132,"endColumn":23,"startColumn":10,"endRow":132},"id":1696,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedAfterPattern"}],"type":"pattern"},{"structure":[],"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)"},"parent":1696,"range":{"endColumn":13,"startColumn":10,"startRow":132,"endRow":132},"id":1697,"text":"let","type":"other"},{"parent":1696,"text":"IdentifierPattern","range":{"endColumn":23,"startColumn":14,"startRow":132,"endRow":132},"id":1698,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"newSquare","kind":"identifier("newSquare")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"type":"pattern"},{"structure":[],"token":{"kind":"identifier("newSquare")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":1698,"range":{"endColumn":23,"endRow":132,"startColumn":14,"startRow":132},"id":1699,"text":"newSquare","type":"other"},{"type":"other","range":{"endColumn":53,"endRow":132,"startColumn":24,"startRow":132},"text":"WhereClause","parent":1695,"id":1700,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeWhereKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.where)","text":"where"},"name":"whereKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereKeywordAndCondition"},{"value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax","name":"condition"},{"value":{"text":"nil"},"name":"unexpectedAfterCondition"}]},{"structure":[],"token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.where)","trailingTrivia":"␣<\/span>"},"parent":1700,"range":{"startColumn":24,"endColumn":29,"endRow":132,"startRow":132},"id":1701,"text":"where","type":"other"},{"type":"expr","range":{"startColumn":30,"endColumn":53,"endRow":132,"startRow":132},"text":"InfixOperatorExpr","parent":1700,"id":1702,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax","name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}]},{"type":"expr","range":{"startRow":132,"startColumn":30,"endRow":132,"endColumn":39},"text":"DeclReferenceExpr","parent":1702,"id":1703,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("newSquare")","text":"newSquare"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"structure":[],"token":{"kind":"identifier("newSquare")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":1703,"id":1704,"range":{"endColumn":39,"startRow":132,"endRow":132,"startColumn":30},"text":"newSquare","type":"other"},{"type":"expr","id":1705,"range":{"endColumn":41,"startRow":132,"endRow":132,"startColumn":40},"text":"BinaryOperatorExpr","parent":1702,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":">","kind":"binaryOperator(">")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}]},{"structure":[],"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"binaryOperator(">")"},"parent":1705,"id":1706,"range":{"startRow":132,"endColumn":41,"endRow":132,"startColumn":40},"text":">","type":"other"},{"type":"expr","id":1707,"range":{"startRow":132,"endColumn":53,"endRow":132,"startColumn":42},"text":"DeclReferenceExpr","parent":1702,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"finalSquare","kind":"identifier("finalSquare")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"structure":[],"token":{"leadingTrivia":"","kind":"identifier("finalSquare")","trailingTrivia":""},"parent":1707,"id":1708,"range":{"startColumn":42,"endRow":132,"endColumn":53,"startRow":132},"text":"finalSquare","type":"other"},{"structure":[],"token":{"trailingTrivia":"","kind":"colon","leadingTrivia":""},"parent":1692,"id":1709,"range":{"startColumn":53,"endRow":132,"endColumn":54,"startRow":132},"text":":","type":"other"},{"type":"collection","id":1710,"text":"CodeBlockItemList","structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":1691,"range":{"startColumn":9,"endRow":133,"endColumn":17,"startRow":133}},{"type":"other","id":1711,"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"ContinueStmtSyntax","value":{"text":"ContinueStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":1710,"range":{"endRow":133,"endColumn":17,"startRow":133,"startColumn":9}},{"type":"other","id":1712,"text":"ContinueStmt","structure":[{"name":"unexpectedBeforeContinueKeyword","value":{"text":"nil"}},{"name":"continueKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.continue)","text":"continue"}},{"name":"unexpectedBetweenContinueKeywordAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedAfterLabel","value":{"text":"nil"}}],"parent":1711,"range":{"endColumn":17,"startRow":133,"endRow":133,"startColumn":9}},{"structure":[],"token":{"trailingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.continue)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":1712,"id":1713,"range":{"startRow":133,"startColumn":9,"endRow":133,"endColumn":17},"text":"continue","type":"other"},{"id":1714,"text":"SwitchCase","range":{"startColumn":5,"startRow":134,"endRow":136,"endColumn":32},"structure":[{"name":"unexpectedBeforeAttribute","value":{"text":"nil"}},{"name":"attribute","value":{"text":"nil"}},{"name":"unexpectedBetweenAttributeAndLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"SwitchDefaultLabelSyntax"},"ref":"SwitchDefaultLabelSyntax"},{"name":"unexpectedBetweenLabelAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedAfterStatements","value":{"text":"nil"}}],"type":"other","parent":1677},{"id":1715,"text":"SwitchDefaultLabel","range":{"startColumn":5,"endRow":134,"startRow":134,"endColumn":13},"structure":[{"name":"unexpectedBeforeDefaultKeyword","value":{"text":"nil"}},{"name":"defaultKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.default)","text":"default"}},{"name":"unexpectedBetweenDefaultKeywordAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedAfterColon","value":{"text":"nil"}}],"type":"other","parent":1714},{"structure":[],"token":{"kind":"keyword(SwiftSyntax.Keyword.default)","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":1715,"id":1716,"range":{"startColumn":5,"endRow":134,"endColumn":12,"startRow":134},"text":"default","type":"other"},{"structure":[],"token":{"kind":"colon","trailingTrivia":"","leadingTrivia":""},"parent":1715,"id":1717,"range":{"startColumn":12,"endRow":134,"endColumn":13,"startRow":134},"text":":","type":"other"},{"id":1718,"text":"CodeBlockItemList","range":{"startColumn":9,"endRow":136,"endColumn":32,"startRow":135},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","parent":1714},{"range":{"startColumn":9,"startRow":135,"endColumn":27,"endRow":135},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"InfixOperatorExprSyntax","name":"item","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","id":1719,"type":"other","parent":1718},{"range":{"endRow":135,"startRow":135,"startColumn":9,"endColumn":27},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"text":"InfixOperatorExpr","id":1720,"type":"expr","parent":1719},{"range":{"endColumn":15,"startRow":135,"startColumn":9,"endRow":135},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"square","kind":"identifier("square")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"text":"DeclReferenceExpr","id":1721,"type":"expr","parent":1720},{"structure":[],"token":{"kind":"identifier("square")","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":1721,"range":{"startRow":135,"endRow":135,"startColumn":9,"endColumn":15},"id":1722,"text":"square","type":"other"},{"text":"BinaryOperatorExpr","type":"expr","parent":1720,"range":{"startRow":135,"endRow":135,"startColumn":16,"endColumn":18},"id":1723,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("+=")","text":"+="}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}]},{"structure":[],"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"binaryOperator("+=")"},"parent":1723,"range":{"startRow":135,"startColumn":16,"endRow":135,"endColumn":18},"id":1724,"text":"+=","type":"other"},{"text":"DeclReferenceExpr","type":"expr","parent":1720,"range":{"startRow":135,"startColumn":19,"endRow":135,"endColumn":27},"id":1725,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"diceRoll","kind":"identifier("diceRoll")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"structure":[],"token":{"leadingTrivia":"","kind":"identifier("diceRoll")","trailingTrivia":""},"parent":1725,"range":{"startRow":135,"endColumn":27,"startColumn":19,"endRow":135},"id":1726,"text":"diceRoll","type":"other"},{"text":"CodeBlockItem","type":"other","parent":1718,"range":{"startRow":136,"endColumn":32,"startColumn":9,"endRow":136},"id":1727,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"text":"InfixOperatorExpr","id":1728,"parent":1727,"type":"expr","range":{"endRow":136,"startRow":136,"startColumn":9,"endColumn":32},"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"SubscriptCallExprSyntax"},"ref":"SubscriptCallExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}]},{"text":"DeclReferenceExpr","id":1729,"parent":1728,"type":"expr","range":{"startRow":136,"endColumn":15,"startColumn":9,"endRow":136},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"square","kind":"identifier("square")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"text":"square","token":{"kind":"identifier("square")","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"id":1730,"type":"other","range":{"endColumn":15,"endRow":136,"startRow":136,"startColumn":9},"structure":[],"parent":1729},{"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("+=")","text":"+="}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"text":"BinaryOperatorExpr","range":{"startRow":136,"endColumn":18,"endRow":136,"startColumn":16},"type":"expr","id":1731,"parent":1728},{"text":"+=","token":{"kind":"binaryOperator("+=")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other","id":1732,"structure":[],"range":{"endRow":136,"endColumn":18,"startColumn":16,"startRow":136},"parent":1731},{"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"kind":"leftSquare","text":"["}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"text":"SubscriptCallExpr","range":{"endRow":136,"endColumn":32,"startColumn":19,"startRow":136},"type":"expr","id":1733,"parent":1728},{"type":"expr","id":1734,"parent":1733,"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"board","kind":"identifier("board")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"range":{"startRow":136,"startColumn":19,"endColumn":24,"endRow":136}},{"text":"board","token":{"trailingTrivia":"","kind":"identifier("board")","leadingTrivia":""},"type":"other","id":1735,"structure":[],"range":{"startColumn":19,"endColumn":24,"startRow":136,"endRow":136},"parent":1734},{"text":"[","token":{"trailingTrivia":"","kind":"leftSquare","leadingTrivia":""},"type":"other","id":1736,"structure":[],"range":{"startColumn":24,"endColumn":25,"startRow":136,"endRow":136},"parent":1733},{"type":"collection","id":1737,"parent":1733,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"range":{"startColumn":25,"endColumn":31,"startRow":136,"endRow":136}},{"type":"other","id":1738,"parent":1737,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"startColumn":25,"startRow":136,"endRow":136,"endColumn":31}},{"id":1739,"parent":1738,"type":"expr","text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"square","kind":"identifier("square")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"endRow":136,"startRow":136,"startColumn":25,"endColumn":31}},{"text":"square","token":{"leadingTrivia":"","kind":"identifier("square")","trailingTrivia":""},"id":1740,"type":"other","structure":[],"range":{"startColumn":25,"startRow":136,"endRow":136,"endColumn":31},"parent":1739},{"text":"]","token":{"leadingTrivia":"","kind":"rightSquare","trailingTrivia":""},"id":1741,"type":"other","structure":[],"range":{"startColumn":31,"startRow":136,"endRow":136,"endColumn":32},"parent":1733},{"id":1742,"parent":1733,"type":"collection","text":"MultipleTrailingClosureElementList","structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"range":{"startColumn":32,"startRow":136,"endRow":136,"endColumn":32}},{"text":"}","token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"id":1743,"type":"other","structure":[],"range":{"startRow":137,"startColumn":5,"endRow":137,"endColumn":6},"parent":1667},{"text":"}","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"type":"other","id":1744,"range":{"endColumn":2,"startColumn":1,"endRow":138,"startRow":138},"structure":[],"parent":1629},{"type":"other","parent":1,"range":{"endRow":142,"endColumn":42,"startColumn":1,"startRow":142},"text":"CodeBlockItem","id":1745,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"type":"expr","parent":1745,"range":{"endRow":142,"startColumn":1,"startRow":142,"endColumn":42},"text":"FunctionCallExpr","id":1746,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"id":1747,"parent":1746,"text":"DeclReferenceExpr","range":{"startRow":142,"startColumn":1,"endColumn":6,"endRow":142},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"text":"print","token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>For␣<\/span>Loops<\/span>↲<\/span>\/\/␣<\/span>For-in␣<\/span>loop␣<\/span>with␣<\/span>enumerated()␣<\/span>to␣<\/span>get␣<\/span>index␣<\/span>and␣<\/span>value<\/span>↲<\/span>"},"id":1748,"type":"other","range":{"endColumn":6,"startRow":142,"startColumn":1,"endRow":142},"structure":[],"parent":1747},{"text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"id":1749,"type":"other","range":{"endColumn":7,"startRow":142,"startColumn":6,"endRow":142},"structure":[],"parent":1746},{"id":1750,"parent":1746,"text":"LabeledExprList","range":{"endColumn":41,"startRow":142,"startColumn":7,"endRow":142},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"id":1751,"parent":1750,"text":"LabeledExpr","range":{"startRow":142,"startColumn":7,"endRow":142,"endColumn":41},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"range":{"startRow":142,"endColumn":41,"endRow":142,"startColumn":7},"text":"StringLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments","ref":"StringLiteralSegmentListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"parent":1751,"type":"expr","id":1752},{"text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"type":"other","id":1753,"range":{"startRow":142,"endRow":142,"startColumn":7,"endColumn":8},"structure":[],"parent":1752},{"type":"collection","id":1754,"parent":1752,"range":{"startColumn":8,"endRow":142,"startRow":142,"endColumn":40},"text":"StringLiteralSegmentList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}]},{"type":"other","id":1755,"parent":1754,"range":{"startRow":142,"startColumn":8,"endRow":142,"endColumn":10},"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"\\n","kind":"stringSegment("\\\\n")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"text":"\\n","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("\\\\n")"},"type":"other","id":1756,"range":{"startRow":142,"endRow":142,"startColumn":8,"endColumn":10},"structure":[],"parent":1755},{"type":"other","id":1757,"parent":1754,"range":{"startRow":142,"endRow":142,"startColumn":10,"endColumn":40},"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("=== For-in with Enumerated ===")","text":"=== For-in with Enumerated ==="}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"text":"===␣<\/span>For-in␣<\/span>with␣<\/span>Enumerated␣<\/span>===","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("=== For-in with Enumerated ===")"},"type":"other","id":1758,"range":{"startColumn":10,"endRow":142,"endColumn":40,"startRow":142},"structure":[],"parent":1757},{"text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"type":"other","id":1759,"range":{"startColumn":40,"endRow":142,"endColumn":41,"startRow":142},"structure":[],"parent":1752},{"text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"type":"other","id":1760,"range":{"startColumn":41,"endRow":142,"endColumn":42,"startRow":142},"structure":[],"parent":1746},{"type":"collection","id":1761,"parent":1746,"range":{"startColumn":42,"endRow":142,"endColumn":42,"startRow":142},"text":"MultipleTrailingClosureElementList","structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"type":"other","id":1762,"parent":1,"range":{"startColumn":1,"startRow":143,"endColumn":2,"endRow":145},"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ForStmtSyntax"},"name":"item","ref":"ForStmtSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"text":"ForStmt","id":1763,"range":{"startRow":143,"endRow":145,"endColumn":2,"startColumn":1},"type":"other","parent":1762,"structure":[{"name":"unexpectedBeforeForKeyword","value":{"text":"nil"}},{"name":"forKeyword","value":{"text":"for","kind":"keyword(SwiftSyntax.Keyword.for)"}},{"name":"unexpectedBetweenForKeywordAndTryKeyword","value":{"text":"nil"}},{"name":"tryKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenTryKeywordAndAwaitKeyword","value":{"text":"nil"}},{"name":"awaitKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenAwaitKeywordAndCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenCaseKeywordAndPattern","value":{"text":"nil"}},{"name":"pattern","ref":"TuplePatternSyntax","value":{"text":"TuplePatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInKeyword"},{"value":{"text":"in","kind":"keyword(SwiftSyntax.Keyword.in)"},"name":"inKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenInKeywordAndSequence"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"sequence"},{"value":{"text":"nil"},"name":"unexpectedBetweenSequenceAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndBody"},{"value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax","name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}]},{"text":"for","token":{"kind":"keyword(SwiftSyntax.Keyword.for)","leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>"},"id":1764,"type":"other","structure":[],"range":{"startColumn":1,"startRow":143,"endRow":143,"endColumn":4},"parent":1763},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"ref":"TuplePatternElementListSyntax","value":{"text":"TuplePatternElementListSyntax"},"name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":1765,"text":"TuplePattern","type":"pattern","parent":1763,"range":{"startColumn":5,"startRow":143,"endRow":143,"endColumn":18}},{"text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"type":"other","id":1766,"structure":[],"range":{"startRow":143,"endRow":143,"endColumn":6,"startColumn":5},"parent":1765},{"structure":[{"value":{"text":"TuplePatternElementSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"text":"TuplePatternElementList","range":{"startRow":143,"endRow":143,"endColumn":17,"startColumn":6},"type":"collection","id":1767,"parent":1765},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndPattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"kind":"comma","text":","}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"TuplePatternElement","range":{"endColumn":12,"startColumn":6,"endRow":143,"startRow":143},"type":"other","id":1768,"parent":1767},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"index","kind":"identifier("index")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"text":"IdentifierPattern","range":{"startRow":143,"endColumn":11,"startColumn":6,"endRow":143},"type":"pattern","id":1769,"parent":1768},{"text":"index","token":{"kind":"identifier("index")","leadingTrivia":"","trailingTrivia":""},"id":1770,"type":"other","structure":[],"range":{"startRow":143,"endColumn":11,"startColumn":6,"endRow":143},"parent":1769},{"text":",","token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":1771,"type":"other","structure":[],"range":{"startRow":143,"endColumn":12,"startColumn":11,"endRow":143},"parent":1768},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndPattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":1767,"range":{"startRow":143,"endColumn":17,"startColumn":13,"endRow":143},"id":1772,"text":"TuplePatternElement","type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("name")","text":"name"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"parent":1772,"range":{"startColumn":13,"endRow":143,"startRow":143,"endColumn":17},"id":1773,"text":"IdentifierPattern","type":"pattern"},{"text":"name","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"id":1774,"type":"other","structure":[],"range":{"startRow":143,"startColumn":13,"endRow":143,"endColumn":17},"parent":1773},{"text":")","token":{"kind":"rightParen","trailingTrivia":"␣<\/span>","leadingTrivia":""},"type":"other","id":1775,"range":{"endColumn":18,"endRow":143,"startColumn":17,"startRow":143},"structure":[],"parent":1765},{"type":"other","text":"in","structure":[],"id":1776,"range":{"endColumn":21,"endRow":143,"startColumn":19,"startRow":143},"parent":1763,"token":{"kind":"keyword(SwiftSyntax.Keyword.in)","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"parent":1763,"range":{"endColumn":40,"endRow":143,"startColumn":22,"startRow":143},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"MemberAccessExprSyntax","name":"calledExpression","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","id":1777,"text":"FunctionCallExpr"},{"parent":1777,"range":{"endColumn":38,"startRow":143,"startColumn":22,"endRow":143},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"type":"expr","id":1778,"text":"MemberAccessExpr"},{"parent":1778,"type":"expr","id":1779,"text":"DeclReferenceExpr","range":{"endColumn":27,"startRow":143,"endRow":143,"startColumn":22},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("names")","text":"names"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","text":"names","structure":[],"id":1780,"range":{"endColumn":27,"startRow":143,"startColumn":22,"endRow":143},"parent":1779,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("names")"}},{"type":"other","text":".","structure":[],"id":1781,"range":{"endColumn":28,"startRow":143,"startColumn":27,"endRow":143},"parent":1778,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"}},{"parent":1778,"type":"expr","id":1782,"text":"DeclReferenceExpr","range":{"endColumn":38,"startRow":143,"startColumn":28,"endRow":143},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("enumerated")","text":"enumerated"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","text":"enumerated","structure":[],"id":1783,"range":{"startColumn":28,"endRow":143,"startRow":143,"endColumn":38},"parent":1782,"token":{"kind":"identifier("enumerated")","trailingTrivia":"","leadingTrivia":""}},{"type":"other","text":"(","structure":[],"id":1784,"range":{"startColumn":38,"endRow":143,"startRow":143,"endColumn":39},"parent":1777,"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""}},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","id":1785,"parent":1777,"text":"LabeledExprList","range":{"startColumn":39,"endRow":143,"startRow":143,"endColumn":39}},{"type":"other","text":")","structure":[],"id":1786,"range":{"startRow":143,"endRow":143,"startColumn":39,"endColumn":40},"parent":1777,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":"␣<\/span>"}},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","id":1787,"parent":1777,"text":"MultipleTrailingClosureElementList","range":{"startRow":143,"endRow":143,"startColumn":41,"endColumn":41}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","id":1788,"parent":1763,"text":"CodeBlock","range":{"startRow":143,"startColumn":41,"endRow":145,"endColumn":2}},{"type":"other","text":"{","structure":[],"id":1789,"range":{"startColumn":41,"startRow":143,"endColumn":42,"endRow":143},"parent":1788,"token":{"kind":"leftBrace","trailingTrivia":"","leadingTrivia":""}},{"id":1790,"type":"collection","text":"CodeBlockItemList","parent":1788,"range":{"startColumn":5,"startRow":144,"endColumn":31,"endRow":144},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"id":1791,"type":"other","text":"CodeBlockItem","parent":1790,"range":{"endRow":144,"startRow":144,"endColumn":31,"startColumn":5},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"id":1792,"type":"expr","text":"FunctionCallExpr","parent":1791,"range":{"startColumn":5,"endColumn":31,"startRow":144,"endRow":144},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"parent":1792,"text":"DeclReferenceExpr","range":{"startColumn":5,"startRow":144,"endRow":144,"endColumn":10},"id":1793,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"text":"print","type":"other","structure":[],"id":1794,"range":{"startRow":144,"endRow":144,"startColumn":5,"endColumn":10},"parent":1793,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")","trailingTrivia":""}},{"text":"(","type":"other","structure":[],"id":1795,"range":{"startRow":144,"endRow":144,"startColumn":10,"endColumn":11},"parent":1792,"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""}},{"parent":1792,"text":"LabeledExprList","range":{"startRow":144,"endRow":144,"startColumn":11,"endColumn":30},"id":1796,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"parent":1796,"text":"LabeledExpr","range":{"endColumn":30,"startRow":144,"endRow":144,"startColumn":11},"id":1797,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"parent":1797,"id":1798,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"text":"StringLiteralExpr","range":{"endRow":144,"startColumn":11,"endColumn":30,"startRow":144},"type":"expr"},{"text":""","type":"other","structure":[],"id":1799,"range":{"endRow":144,"startColumn":11,"endColumn":12,"startRow":144},"parent":1798,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""}},{"text":"StringLiteralSegmentList","range":{"endRow":144,"startColumn":12,"endColumn":29,"startRow":144},"id":1800,"type":"collection","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}],"parent":1798},{"text":"StringSegment","range":{"startRow":144,"endRow":144,"startColumn":12,"endColumn":12},"id":1801,"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"parent":1800},{"text":"","type":"other","structure":[],"id":1802,"range":{"startColumn":12,"endColumn":12,"endRow":144,"startRow":144},"parent":1801,"token":{"leadingTrivia":"","kind":"stringSegment("")","trailingTrivia":""}},{"text":"ExpressionSegment","range":{"startColumn":12,"endColumn":20,"endRow":144,"startRow":144},"id":1803,"type":"other","structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":1800},{"text":"\\","type":"other","structure":[],"id":1804,"range":{"endColumn":13,"startColumn":12,"endRow":144,"startRow":144},"parent":1803,"token":{"kind":"backslash","leadingTrivia":"","trailingTrivia":""}},{"text":"(","type":"other","structure":[],"id":1805,"range":{"endColumn":14,"startColumn":13,"endRow":144,"startRow":144},"parent":1803,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""}},{"text":"LabeledExprList","type":"collection","range":{"endColumn":19,"startColumn":14,"endRow":144,"startRow":144},"parent":1803,"id":1806,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"text":"LabeledExpr","type":"other","range":{"endColumn":19,"startColumn":14,"startRow":144,"endRow":144},"parent":1806,"id":1807,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"parent":1807,"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("index")","text":"index"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","range":{"startRow":144,"startColumn":14,"endRow":144,"endColumn":19},"id":1808},{"text":"index","type":"other","structure":[],"id":1809,"range":{"startRow":144,"endRow":144,"startColumn":14,"endColumn":19},"parent":1808,"token":{"kind":"identifier("index")","leadingTrivia":"","trailingTrivia":""}},{"text":")","type":"other","structure":[],"id":1810,"range":{"startRow":144,"endRow":144,"startColumn":19,"endColumn":20},"parent":1803,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""}},{"parent":1800,"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":": ","kind":"stringSegment(": ")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","range":{"startRow":144,"endRow":144,"startColumn":20,"endColumn":22},"id":1811},{"text":":␣<\/span>","type":"other","structure":[],"id":1812,"range":{"startRow":144,"startColumn":20,"endRow":144,"endColumn":22},"parent":1811,"token":{"leadingTrivia":"","kind":"stringSegment(": ")","trailingTrivia":""}},{"text":"ExpressionSegment","structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"name":"expressions","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":1813,"range":{"endColumn":29,"endRow":144,"startRow":144,"startColumn":22},"type":"other","parent":1800},{"type":"other","text":"\\","structure":[],"id":1814,"range":{"endColumn":23,"startRow":144,"endRow":144,"startColumn":22},"parent":1813,"token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""}},{"type":"other","text":"(","structure":[],"id":1815,"range":{"endColumn":24,"startRow":144,"endRow":144,"startColumn":23},"parent":1813,"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""}},{"range":{"endColumn":28,"startRow":144,"endRow":144,"startColumn":24},"type":"collection","id":1816,"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":1813},{"range":{"startRow":144,"endRow":144,"endColumn":28,"startColumn":24},"type":"other","id":1817,"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1816},{"id":1818,"parent":1817,"range":{"startRow":144,"endColumn":28,"endRow":144,"startColumn":24},"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"text":"name","type":"other","structure":[],"id":1819,"range":{"startColumn":24,"endRow":144,"startRow":144,"endColumn":28},"parent":1818,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("name")"}},{"text":")","type":"other","structure":[],"id":1820,"range":{"startColumn":28,"endRow":144,"startRow":144,"endColumn":29},"parent":1813,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"}},{"id":1821,"parent":1800,"range":{"startColumn":29,"endRow":144,"startRow":144,"endColumn":29},"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("")","text":""}},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other"},{"type":"other","text":"","structure":[],"id":1822,"range":{"endRow":144,"startColumn":29,"startRow":144,"endColumn":29},"parent":1821,"token":{"trailingTrivia":"","kind":"stringSegment("")","leadingTrivia":""}},{"text":""","type":"other","id":1823,"parent":1798,"range":{"endRow":144,"startColumn":29,"startRow":144,"endColumn":30},"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"structure":[]},{"text":")","type":"other","id":1824,"parent":1792,"range":{"endRow":144,"startColumn":30,"startRow":144,"endColumn":31},"token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"structure":[]},{"parent":1792,"range":{"endRow":144,"startColumn":31,"startRow":144,"endColumn":31},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":1825,"type":"collection","text":"MultipleTrailingClosureElementList"},{"text":"}","type":"other","id":1826,"parent":1788,"range":{"endRow":145,"endColumn":2,"startRow":145,"startColumn":1},"token":{"trailingTrivia":"","kind":"rightBrace","leadingTrivia":"↲<\/span>"},"structure":[]},{"parent":1,"range":{"endRow":148,"endColumn":44,"startRow":148,"startColumn":1},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":1827,"type":"other","text":"CodeBlockItem"},{"parent":1827,"range":{"endRow":148,"startColumn":1,"startRow":148,"endColumn":44},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":1828,"type":"expr","text":"FunctionCallExpr"},{"parent":1828,"text":"DeclReferenceExpr","type":"expr","id":1829,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"startColumn":1,"endRow":148,"startRow":148,"endColumn":6}},{"text":"print","type":"other","id":1830,"parent":1829,"range":{"endColumn":6,"endRow":148,"startRow":148,"startColumn":1},"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>For-in␣<\/span>loop␣<\/span>with␣<\/span>where␣<\/span>clause<\/span>↲<\/span>","trailingTrivia":"","kind":"identifier("print")"},"structure":[]},{"text":"(","type":"other","id":1831,"parent":1828,"range":{"startRow":148,"endColumn":7,"startColumn":6,"endRow":148},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"structure":[]},{"text":"LabeledExprList","range":{"startRow":148,"endColumn":43,"startColumn":7,"endRow":148},"id":1832,"parent":1828,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"text":"LabeledExpr","range":{"endColumn":43,"endRow":148,"startRow":148,"startColumn":7},"id":1833,"parent":1832,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"text":"StringLiteralExpr","range":{"endRow":148,"startRow":148,"startColumn":7,"endColumn":43},"id":1834,"parent":1833,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"type":"expr"},{"text":""","type":"other","id":1835,"parent":1834,"range":{"startColumn":7,"startRow":148,"endRow":148,"endColumn":8},"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"structure":[]},{"type":"collection","range":{"startColumn":8,"startRow":148,"endRow":148,"endColumn":42},"parent":1834,"text":"StringLiteralSegmentList","id":1836,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"2"}}]},{"type":"other","range":{"endColumn":10,"endRow":148,"startColumn":8,"startRow":148},"parent":1836,"text":"StringSegment","id":1837,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("\\\\n")","text":"\\n"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"text":"\\n","type":"other","id":1838,"parent":1837,"range":{"startRow":148,"endRow":148,"startColumn":8,"endColumn":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("\\\\n")"},"structure":[]},{"parent":1836,"id":1839,"range":{"startColumn":10,"startRow":148,"endColumn":42,"endRow":148},"type":"other","text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"=== For-in with Where Clause ===","kind":"stringSegment("=== For-in with Where Clause ===")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"text":"===␣<\/span>For-in␣<\/span>with␣<\/span>Where␣<\/span>Clause␣<\/span>===","type":"other","id":1840,"parent":1839,"range":{"startRow":148,"endRow":148,"startColumn":10,"endColumn":42},"token":{"kind":"stringSegment("=== For-in with Where Clause ===")","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"text":""","type":"other","id":1841,"parent":1834,"range":{"startRow":148,"endRow":148,"startColumn":42,"endColumn":43},"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"text":")","type":"other","id":1842,"parent":1828,"range":{"startRow":148,"endRow":148,"startColumn":43,"endColumn":44},"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"parent":1828,"type":"collection","id":1843,"range":{"startRow":148,"endRow":148,"startColumn":44,"endColumn":44},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"text":"MultipleTrailingClosureElementList"},{"parent":1,"type":"other","id":1844,"range":{"startRow":149,"endRow":149,"startColumn":1,"endColumn":46},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"text":"CodeBlockItem"},{"parent":1844,"type":"decl","id":1845,"range":{"startRow":149,"startColumn":1,"endRow":149,"endColumn":46},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"name":"attributes","ref":"AttributeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"text":"VariableDecl"},{"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"parent":1845,"type":"collection","id":1846,"text":"AttributeList","range":{"endRow":148,"startColumn":44,"startRow":148,"endColumn":44}},{"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":1845,"type":"collection","id":1847,"text":"DeclModifierList","range":{"endRow":148,"startColumn":44,"startRow":148,"endColumn":44}},{"text":"let","type":"other","id":1848,"parent":1845,"range":{"endColumn":4,"endRow":149,"startColumn":1,"startRow":149},"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"structure":[]},{"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":1845,"type":"collection","id":1849,"text":"PatternBindingList","range":{"endColumn":46,"endRow":149,"startColumn":5,"startRow":149}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":1849,"type":"other","id":1850,"text":"PatternBinding","range":{"startRow":149,"endRow":149,"endColumn":46,"startColumn":5}},{"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"numbers","kind":"identifier("numbers")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":1851,"parent":1850,"text":"IdentifierPattern","range":{"endColumn":12,"endRow":149,"startColumn":5,"startRow":149},"type":"pattern"},{"text":"numbers","type":"other","id":1852,"parent":1851,"range":{"startColumn":5,"endRow":149,"endColumn":12,"startRow":149},"token":{"leadingTrivia":"","kind":"identifier("numbers")","trailingTrivia":"␣<\/span>"},"structure":[]},{"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"ArrayExprSyntax"},"ref":"ArrayExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":1853,"parent":1850,"text":"InitializerClause","range":{"startColumn":13,"endRow":149,"endColumn":46,"startRow":149},"type":"other"},{"text":"=","type":"other","id":1854,"parent":1853,"range":{"endColumn":14,"endRow":149,"startRow":149,"startColumn":13},"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"structure":[]},{"type":"expr","id":1855,"range":{"endColumn":46,"endRow":149,"startRow":149,"startColumn":15},"structure":[{"name":"unexpectedBeforeLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"kind":"leftSquare","text":"["}},{"name":"unexpectedBetweenLeftSquareAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"ArrayElementListSyntax"},"ref":"ArrayElementListSyntax"},{"name":"unexpectedBetweenElementsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"text":"]","kind":"rightSquare"}},{"name":"unexpectedAfterRightSquare","value":{"text":"nil"}}],"text":"ArrayExpr","parent":1853},{"text":"[","type":"other","id":1856,"parent":1855,"range":{"startColumn":15,"startRow":149,"endRow":149,"endColumn":16},"token":{"leadingTrivia":"","kind":"leftSquare","trailingTrivia":""},"structure":[]},{"type":"collection","id":1857,"range":{"startColumn":16,"startRow":149,"endRow":149,"endColumn":45},"structure":[{"name":"Element","value":{"text":"ArrayElementSyntax"}},{"name":"Count","value":{"text":"10"}}],"text":"ArrayElementList","parent":1855},{"type":"other","id":1858,"range":{"startColumn":16,"endRow":149,"startRow":149,"endColumn":18},"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"kind":"comma","text":","}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"ArrayElement","parent":1857},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"1","kind":"integerLiteral("1")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"parent":1858,"type":"expr","range":{"startRow":149,"endColumn":17,"startColumn":16,"endRow":149},"id":1859,"text":"IntegerLiteralExpr"},{"text":"1","type":"other","id":1860,"parent":1859,"range":{"startRow":149,"startColumn":16,"endRow":149,"endColumn":17},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("1")"},"structure":[]},{"text":",","type":"other","id":1861,"parent":1858,"range":{"startRow":149,"startColumn":17,"endRow":149,"endColumn":18},"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"comma"},"structure":[]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":1857,"type":"other","range":{"startRow":149,"startColumn":19,"endRow":149,"endColumn":21},"id":1862,"text":"ArrayElement"},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"value":{"kind":"integerLiteral("2")","text":"2"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":1862,"type":"expr","range":{"startColumn":19,"startRow":149,"endColumn":20,"endRow":149},"id":1863,"text":"IntegerLiteralExpr"},{"text":"2","type":"other","id":1864,"parent":1863,"range":{"startRow":149,"startColumn":19,"endRow":149,"endColumn":20},"token":{"leadingTrivia":"","kind":"integerLiteral("2")","trailingTrivia":""},"structure":[]},{"text":",","type":"other","id":1865,"parent":1862,"range":{"startRow":149,"startColumn":20,"endRow":149,"endColumn":21},"token":{"leadingTrivia":"","kind":"comma","trailingTrivia":"␣<\/span>"},"structure":[]},{"id":1866,"text":"ArrayElement","range":{"startRow":149,"startColumn":22,"endRow":149,"endColumn":24},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":1857},{"id":1867,"text":"IntegerLiteralExpr","range":{"endRow":149,"startColumn":22,"endColumn":23,"startRow":149},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"3","kind":"integerLiteral("3")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","parent":1866},{"text":"3","type":"other","id":1868,"parent":1867,"range":{"endRow":149,"endColumn":23,"startRow":149,"startColumn":22},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("3")"},"structure":[]},{"text":",","type":"other","id":1869,"parent":1866,"range":{"endRow":149,"endColumn":24,"startRow":149,"startColumn":23},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"structure":[]},{"id":1870,"text":"ArrayElement","range":{"endRow":149,"endColumn":27,"startRow":149,"startColumn":25},"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"kind":"comma","text":","}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","parent":1857},{"parent":1870,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"4","kind":"integerLiteral("4")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","id":1871,"text":"IntegerLiteralExpr","range":{"endRow":149,"endColumn":26,"startColumn":25,"startRow":149}},{"text":"4","type":"other","id":1872,"parent":1871,"range":{"startColumn":25,"startRow":149,"endRow":149,"endColumn":26},"token":{"kind":"integerLiteral("4")","leadingTrivia":"","trailingTrivia":""},"structure":[]},{"id":1873,"structure":[],"range":{"startColumn":26,"startRow":149,"endRow":149,"endColumn":27},"text":",","token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other","parent":1870},{"parent":1857,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","id":1874,"text":"ArrayElement","range":{"startColumn":28,"startRow":149,"endRow":149,"endColumn":30}},{"parent":1874,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"5","kind":"integerLiteral("5")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","id":1875,"text":"IntegerLiteralExpr","range":{"startColumn":28,"endRow":149,"endColumn":29,"startRow":149}},{"parent":1875,"structure":[],"range":{"endColumn":29,"startRow":149,"startColumn":28,"endRow":149},"text":"5","token":{"trailingTrivia":"","kind":"integerLiteral("5")","leadingTrivia":""},"id":1876,"type":"other"},{"parent":1874,"structure":[],"range":{"endColumn":30,"startRow":149,"startColumn":29,"endRow":149},"text":",","token":{"trailingTrivia":"␣<\/span>","kind":"comma","leadingTrivia":""},"id":1877,"type":"other"},{"range":{"endColumn":33,"startRow":149,"startColumn":31,"endRow":149},"id":1878,"type":"other","parent":1857,"text":"ArrayElement","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startColumn":31,"startRow":149,"endColumn":32,"endRow":149},"id":1879,"type":"expr","parent":1878,"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("6")","text":"6"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"parent":1879,"structure":[],"range":{"startRow":149,"endColumn":32,"startColumn":31,"endRow":149},"text":"6","token":{"kind":"integerLiteral("6")","leadingTrivia":"","trailingTrivia":""},"id":1880,"type":"other"},{"parent":1878,"structure":[],"range":{"startRow":149,"endColumn":33,"startColumn":32,"endRow":149},"text":",","token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":1881,"type":"other"},{"range":{"startRow":149,"endColumn":36,"startColumn":34,"endRow":149},"id":1882,"type":"other","parent":1857,"text":"ArrayElement","structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"ref":"IntegerLiteralExprSyntax","name":"expression","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"7","kind":"integerLiteral("7")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":1882,"id":1883,"text":"IntegerLiteralExpr","type":"expr","range":{"startColumn":34,"endColumn":35,"endRow":149,"startRow":149}},{"type":"other","structure":[],"range":{"endRow":149,"startColumn":34,"endColumn":35,"startRow":149},"text":"7","token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("7")"},"id":1884,"parent":1883},{"type":"other","structure":[],"range":{"endRow":149,"startColumn":35,"endColumn":36,"startRow":149},"text":",","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"id":1885,"parent":1882},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":1857,"id":1886,"text":"ArrayElement","type":"other","range":{"endRow":149,"startColumn":37,"endColumn":39,"startRow":149}},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"8","kind":"integerLiteral("8")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"parent":1886,"id":1887,"text":"IntegerLiteralExpr","type":"expr","range":{"endRow":149,"startRow":149,"endColumn":38,"startColumn":37}},{"parent":1887,"structure":[],"range":{"startColumn":37,"endColumn":38,"startRow":149,"endRow":149},"text":"8","token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("8")"},"type":"other","id":1888},{"parent":1886,"structure":[],"range":{"startColumn":38,"endColumn":39,"startRow":149,"endRow":149},"text":",","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"comma"},"type":"other","id":1889},{"type":"other","id":1890,"text":"ArrayElement","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"range":{"startColumn":40,"endColumn":42,"startRow":149,"endRow":149},"parent":1857},{"type":"expr","id":1891,"text":"IntegerLiteralExpr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("9")","text":"9"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"startColumn":40,"startRow":149,"endRow":149,"endColumn":41},"parent":1890},{"parent":1891,"structure":[],"range":{"endRow":149,"startRow":149,"startColumn":40,"endColumn":41},"text":"9","token":{"kind":"integerLiteral("9")","trailingTrivia":"","leadingTrivia":""},"type":"other","id":1892},{"parent":1890,"structure":[],"range":{"endRow":149,"startRow":149,"startColumn":41,"endColumn":42},"text":",","token":{"kind":"comma","trailingTrivia":"␣<\/span>","leadingTrivia":""},"type":"other","id":1893},{"type":"other","id":1894,"text":"ArrayElement","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","name":"expression","value":{"text":"IntegerLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endRow":149,"startRow":149,"startColumn":43,"endColumn":45},"parent":1857},{"id":1895,"text":"IntegerLiteralExpr","range":{"endColumn":45,"startRow":149,"startColumn":43,"endRow":149},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"10","kind":"integerLiteral("10")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"parent":1894},{"parent":1895,"structure":[],"range":{"startRow":149,"endRow":149,"startColumn":43,"endColumn":45},"text":"10","token":{"leadingTrivia":"","kind":"integerLiteral("10")","trailingTrivia":""},"id":1896,"type":"other"},{"parent":1855,"structure":[],"range":{"startRow":149,"endRow":149,"startColumn":45,"endColumn":46},"text":"]","token":{"leadingTrivia":"","kind":"rightSquare","trailingTrivia":""},"id":1897,"type":"other"},{"id":1898,"text":"CodeBlockItem","range":{"startRow":150,"endRow":152,"startColumn":1,"endColumn":2},"type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"ForStmtSyntax"},"ref":"ForStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":1},{"id":1899,"text":"ForStmt","range":{"endRow":152,"startRow":150,"startColumn":1,"endColumn":2},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeForKeyword"},{"name":"forKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.for)","text":"for"}},{"name":"unexpectedBetweenForKeywordAndTryKeyword","value":{"text":"nil"}},{"name":"tryKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenTryKeywordAndAwaitKeyword","value":{"text":"nil"}},{"name":"awaitKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenAwaitKeywordAndCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenCaseKeywordAndPattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInKeyword","value":{"text":"nil"}},{"name":"inKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.in)","text":"in"}},{"name":"unexpectedBetweenInKeywordAndSequence","value":{"text":"nil"}},{"name":"sequence","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenSequenceAndWhereClause","value":{"text":"nil"}},{"name":"whereClause","ref":"WhereClauseSyntax","value":{"text":"WhereClauseSyntax"}},{"name":"unexpectedBetweenWhereClauseAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"parent":1898},{"id":1900,"structure":[],"range":{"startRow":150,"startColumn":1,"endRow":150,"endColumn":4},"text":"for","token":{"kind":"keyword(SwiftSyntax.Keyword.for)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>"},"type":"other","parent":1899},{"range":{"startRow":150,"startColumn":5,"endRow":150,"endColumn":11},"type":"pattern","structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"number","kind":"identifier("number")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"parent":1899,"text":"IdentifierPattern","id":1901},{"id":1902,"structure":[],"range":{"endRow":150,"startRow":150,"startColumn":5,"endColumn":11},"text":"number","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("number")","leadingTrivia":""},"type":"other","parent":1901},{"id":1903,"structure":[],"range":{"endRow":150,"startRow":150,"startColumn":12,"endColumn":14},"text":"in","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.in)","leadingTrivia":""},"type":"other","parent":1899},{"range":{"endRow":150,"startRow":150,"startColumn":15,"endColumn":22},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"numbers","kind":"identifier("numbers")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":1899,"text":"DeclReferenceExpr","id":1904},{"id":1905,"structure":[],"range":{"endColumn":22,"endRow":150,"startRow":150,"startColumn":15},"text":"numbers","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("numbers")"},"type":"other","parent":1904},{"range":{"endColumn":44,"endRow":150,"startRow":150,"startColumn":23},"type":"other","structure":[{"name":"unexpectedBeforeWhereKeyword","value":{"text":"nil"}},{"name":"whereKeyword","value":{"text":"where","kind":"keyword(SwiftSyntax.Keyword.where)"}},{"name":"unexpectedBetweenWhereKeywordAndCondition","value":{"text":"nil"}},{"name":"condition","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedAfterCondition","value":{"text":"nil"}}],"parent":1899,"text":"WhereClause","id":1906},{"type":"other","structure":[],"range":{"startColumn":23,"endRow":150,"startRow":150,"endColumn":28},"text":"where","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.where)"},"id":1907,"parent":1906},{"parent":1906,"range":{"startColumn":29,"endRow":150,"startRow":150,"endColumn":44},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"leftOperand","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"BinaryOperatorExprSyntax"},"name":"operator","ref":"BinaryOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"id":1908,"text":"InfixOperatorExpr","type":"expr"},{"parent":1908,"range":{"startRow":150,"endColumn":39,"endRow":150,"startColumn":29},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax","name":"operator"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"id":1909,"text":"InfixOperatorExpr","type":"expr"},{"text":"DeclReferenceExpr","parent":1909,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("number")","text":"number"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"range":{"startRow":150,"endRow":150,"endColumn":35,"startColumn":29},"type":"expr","id":1910},{"id":1911,"structure":[],"range":{"startColumn":29,"endRow":150,"endColumn":35,"startRow":150},"text":"number","token":{"leadingTrivia":"","kind":"identifier("number")","trailingTrivia":"␣<\/span>"},"type":"other","parent":1910},{"text":"BinaryOperatorExpr","parent":1909,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"text":"%","kind":"binaryOperator("%")"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"range":{"startColumn":36,"endRow":150,"endColumn":37,"startRow":150},"type":"expr","id":1912},{"id":1913,"structure":[],"range":{"endColumn":37,"endRow":150,"startColumn":36,"startRow":150},"text":"%","token":{"leadingTrivia":"","kind":"binaryOperator("%")","trailingTrivia":"␣<\/span>"},"type":"other","parent":1912},{"text":"IntegerLiteralExpr","parent":1909,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"2","kind":"integerLiteral("2")"}},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"range":{"endColumn":39,"endRow":150,"startColumn":38,"startRow":150},"type":"expr","id":1914},{"type":"other","structure":[],"range":{"endColumn":39,"startRow":150,"endRow":150,"startColumn":38},"text":"2","token":{"kind":"integerLiteral("2")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":1915,"parent":1914},{"range":{"endColumn":42,"startRow":150,"endRow":150,"startColumn":40},"parent":1908,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator("==")","text":"=="}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"id":1916,"type":"expr","text":"BinaryOperatorExpr"},{"id":1917,"token":{"kind":"binaryOperator("==")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endRow":150,"startRow":150,"startColumn":40,"endColumn":42},"text":"==","type":"other","parent":1916,"structure":[]},{"range":{"endRow":150,"startRow":150,"startColumn":43,"endColumn":44},"parent":1908,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":1918,"type":"expr","text":"IntegerLiteralExpr"},{"id":1919,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"integerLiteral("0")"},"range":{"endRow":150,"startRow":150,"endColumn":44,"startColumn":43},"text":"0","type":"other","parent":1918,"structure":[]},{"range":{"endRow":152,"startRow":150,"endColumn":2,"startColumn":45},"parent":1899,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"id":1920,"type":"other","text":"CodeBlock"},{"id":1921,"token":{"trailingTrivia":"","kind":"leftBrace","leadingTrivia":""},"range":{"endColumn":46,"startRow":150,"startColumn":45,"endRow":150},"text":"{","type":"other","parent":1920,"structure":[]},{"text":"CodeBlockItemList","range":{"endColumn":36,"startRow":151,"startColumn":5,"endRow":151},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":1922,"parent":1920},{"text":"CodeBlockItem","range":{"startColumn":5,"startRow":151,"endColumn":36,"endRow":151},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","id":1923,"parent":1922},{"text":"FunctionCallExpr","range":{"endRow":151,"endColumn":36,"startColumn":5,"startRow":151},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","id":1924,"parent":1923},{"text":"DeclReferenceExpr","range":{"endRow":151,"startRow":151,"endColumn":10,"startColumn":5},"parent":1924,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","id":1925},{"id":1926,"token":{"kind":"identifier("print")","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"startRow":151,"endRow":151,"startColumn":5,"endColumn":10},"text":"print","type":"other","parent":1925,"structure":[]},{"id":1927,"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"range":{"startRow":151,"endRow":151,"startColumn":10,"endColumn":11},"text":"(","type":"other","parent":1924,"structure":[]},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"value":{"text":"1"},"name":"Count"}],"type":"collection","id":1928,"parent":1924,"text":"LabeledExprList","range":{"startRow":151,"startColumn":11,"endRow":151,"endColumn":35}},{"parent":1928,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endRow":151,"endColumn":35,"startRow":151,"startColumn":11},"text":"LabeledExpr","type":"other","id":1929},{"parent":1929,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"range":{"startColumn":11,"startRow":151,"endRow":151,"endColumn":35},"text":"StringLiteralExpr","type":"expr","id":1930},{"id":1931,"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"range":{"endColumn":12,"startColumn":11,"endRow":151,"startRow":151},"text":""","type":"other","parent":1930,"structure":[]},{"text":"StringLiteralSegmentList","range":{"endColumn":34,"startColumn":12,"endRow":151,"startRow":151},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"id":1932,"type":"collection","parent":1930},{"text":"StringSegment","range":{"endRow":151,"startRow":151,"endColumn":25,"startColumn":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Even number: ","kind":"stringSegment("Even number: ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":1933,"type":"other","parent":1932},{"id":1934,"token":{"leadingTrivia":"","kind":"stringSegment("Even number: ")","trailingTrivia":""},"range":{"startColumn":12,"endRow":151,"endColumn":25,"startRow":151},"text":"Even␣<\/span>number:␣<\/span>","type":"other","parent":1933,"structure":[]},{"text":"ExpressionSegment","range":{"startColumn":25,"endRow":151,"endColumn":34,"startRow":151},"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":1935,"type":"other","parent":1932},{"id":1936,"token":{"leadingTrivia":"","kind":"backslash","trailingTrivia":""},"range":{"startRow":151,"endColumn":26,"endRow":151,"startColumn":25},"text":"\\","type":"other","parent":1935,"structure":[]},{"id":1937,"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"range":{"startRow":151,"endColumn":27,"endRow":151,"startColumn":26},"text":"(","type":"other","parent":1935,"structure":[]},{"parent":1935,"text":"LabeledExprList","type":"collection","range":{"startRow":151,"endColumn":33,"endRow":151,"startColumn":27},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":1938},{"parent":1938,"text":"LabeledExpr","type":"other","range":{"startRow":151,"startColumn":27,"endRow":151,"endColumn":33},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":1939},{"parent":1939,"type":"expr","id":1940,"range":{"startColumn":27,"endRow":151,"startRow":151,"endColumn":33},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("number")","text":"number"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"text":"DeclReferenceExpr"},{"id":1941,"token":{"leadingTrivia":"","kind":"identifier("number")","trailingTrivia":""},"range":{"endRow":151,"startRow":151,"endColumn":33,"startColumn":27},"text":"number","type":"other","parent":1940,"structure":[]},{"id":1942,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"range":{"endRow":151,"startRow":151,"endColumn":34,"startColumn":33},"text":")","type":"other","parent":1935,"structure":[]},{"parent":1932,"type":"other","id":1943,"range":{"endRow":151,"startRow":151,"endColumn":34,"startColumn":34},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"","kind":"stringSegment("")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"text":"StringSegment"},{"id":1944,"token":{"trailingTrivia":"","kind":"stringSegment("")","leadingTrivia":""},"range":{"endRow":151,"startColumn":34,"startRow":151,"endColumn":34},"text":"","type":"other","parent":1943,"structure":[]},{"id":1945,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"range":{"endColumn":35,"startColumn":34,"startRow":151,"endRow":151},"text":""","type":"other","parent":1930,"structure":[]},{"id":1946,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"range":{"endColumn":36,"startColumn":35,"startRow":151,"endRow":151},"text":")","type":"other","parent":1924,"structure":[]},{"text":"MultipleTrailingClosureElementList","type":"collection","structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":1924,"id":1947,"range":{"endColumn":36,"startColumn":36,"startRow":151,"endRow":151}},{"id":1948,"token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":"↲<\/span>"},"range":{"endColumn":2,"startColumn":1,"startRow":152,"endRow":152},"text":"}","type":"other","parent":1920,"structure":[]},{"id":1949,"token":{"kind":"endOfFile","trailingTrivia":"","leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>"},"range":{"endColumn":1,"startColumn":1,"startRow":155,"endRow":155},"text":"","type":"other","parent":0,"structure":[]}] diff --git a/Examples/Completed/for_loops/code.swift b/Examples/Completed/for_loops/code.swift new file mode 100644 index 0000000..ca2d2d7 --- /dev/null +++ b/Examples/Completed/for_loops/code.swift @@ -0,0 +1,29 @@ +// MARK: - Basic For-in Loop +// Simple for-in loop over an array +let names = ["Alice", "Bob", "Charlie"] +for name in names { + print("Hello, \(name)!") +} + +// MARK: - For-in with Enumerated +// For-in loop with enumerated() to get index and value +print("\n=== For-in with Enumerated ===") +for (index, name) in names.enumerated() { + print("Index: \(index), Name: \(name)") +} + +// MARK: - For-in with Where Clause +// For-in loop with where clause +print("\n=== For-in with Where Clause ===") +let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +for number in numbers where number % 2 == 0 { + print("Even number: \(number)") +} + +// MARK: - For-in with Dictionary +// For-in loop over dictionary +print("\n=== For-in with Dictionary ===") +let scores = ["Alice": 95, "Bob": 87, "Charlie": 92] +for (name, score) in scores { + print("\(name): \(score)") +} diff --git a/Examples/Completed/for_loops/dsl.swift b/Examples/Completed/for_loops/dsl.swift new file mode 100644 index 0000000..4c8bf36 --- /dev/null +++ b/Examples/Completed/for_loops/dsl.swift @@ -0,0 +1,71 @@ +import SyntaxKit + +// MARK: - For Loops Examples +Group { + // MARK: - Basic For-in Loop + Variable(.let, name: "names", equals: Literal.array([Literal.string("Alice"), Literal.string("Bob"), Literal.string("Charlie")])) + .comment { + Line("MARK: - Basic For-in Loop") + Line("Simple for-in loop over an array") + } + + For(VariableExp("name"), in: VariableExp("names"), then: { + Call("print") { + ParameterExp(unlabeled: "\"Hello, \\(name)!\"") + } + }) + + // MARK: - For-in with Enumerated + Call("print") { + ParameterExp(unlabeled: "\"\\n=== For-in with Enumerated ===\"") + } + .comment { + Line("MARK: - For-in with Enumerated") + Line("For-in loop with enumerated() to get index and value") + } + For(Tuple.patternCodeBlock([VariableExp("index"), VariableExp("name")]), in: VariableExp("names").call("enumerated"), then: { + Call("print") { + ParameterExp(unlabeled: "\"Index: \\(index), Name: \\(name)\"") + } + }) + + // MARK: - For-in with Where Clause + Call("print") { + ParameterExp(unlabeled: "\"\\n=== For-in with Where Clause ===\"") + } + .comment { + Line("MARK: - For-in with Where Clause") + Line("For-in loop with where clause") + } + Variable(.let, name: "numbers", equals: Literal.array([Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), Literal.integer(9), Literal.integer(10)])) + + For(VariableExp("number"), in: VariableExp("numbers"), where: { + Infix("==") { + Infix("%") { + VariableExp("number") + Literal.integer(2) + } + Literal.integer(0) + } + }, then: { + Call("print") { + ParameterExp(unlabeled: "\"Even number: \\(number)\"") + } + }) + + // MARK: - For-in with Dictionary + Call("print") { + ParameterExp(unlabeled: "\"\\n=== For-in with Dictionary ===\"") + } + .comment { + Line("MARK: - For-in with Dictionary") + Line("For-in loop over dictionary") + } + Variable(.let, name: "scores", equals: Literal.dictionary([(Literal.string("Alice"), Literal.integer(95)), (Literal.string("Bob"), Literal.integer(87)), (Literal.string("Charlie"), Literal.integer(92))])) + + For(Tuple.patternCodeBlock([VariableExp("name"), VariableExp("score")]), in: VariableExp("scores"), then: { + Call("print") { + ParameterExp(unlabeled: "\"\\(name): \\(score)\"") + } + }) +} \ No newline at end of file diff --git a/Examples/Completed/for_loops/syntax.json b/Examples/Completed/for_loops/syntax.json new file mode 100644 index 0000000..894fdf5 --- /dev/null +++ b/Examples/Completed/for_loops/syntax.json @@ -0,0 +1 @@ +[{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeShebang"},{"value":{"text":"nil"},"name":"shebang"},{"value":{"text":"nil"},"name":"unexpectedBetweenShebangAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndEndOfFileToken"},{"value":{"text":"","kind":"endOfFile"},"name":"endOfFileToken"},{"value":{"text":"nil"},"name":"unexpectedAfterEndOfFileToken"}],"type":"other","text":"SourceFile","id":0,"range":{"endColumn":1,"endRow":30,"startColumn":1,"startRow":3}},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"10"},"name":"Count"}],"type":"collection","text":"CodeBlockItemList","id":1,"parent":0,"range":{"endColumn":2,"endRow":29,"startColumn":1,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":2,"parent":1,"range":{"endColumn":40,"endRow":3,"startColumn":1,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"type":"decl","text":"VariableDecl","id":3,"parent":2,"range":{"endColumn":40,"endRow":3,"startColumn":1,"startRow":3}},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"AttributeList","id":4,"parent":3,"range":{"endColumn":1,"endRow":1,"startColumn":1,"startRow":1}},{"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"DeclModifierList","id":5,"parent":3,"range":{"endColumn":1,"endRow":1,"startColumn":1,"startRow":1}},{"type":"other","parent":3,"token":{"leadingTrivia":"\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Basic␣<\/span>For-in␣<\/span>Loop<\/span>↲<\/span>\/\/␣<\/span>Simple␣<\/span>for-in␣<\/span>loop␣<\/span>over␣<\/span>an␣<\/span>array<\/span>↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"structure":[],"id":6,"text":"let","range":{"endColumn":4,"endRow":3,"startColumn":1,"startRow":3}},{"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"PatternBindingList","id":7,"parent":3,"range":{"endColumn":40,"endRow":3,"startColumn":5,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"PatternBinding","id":8,"parent":7,"range":{"endColumn":40,"endRow":3,"startColumn":5,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"names","kind":"identifier("names")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":9,"parent":8,"range":{"endColumn":10,"endRow":3,"startColumn":5,"startRow":3}},{"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("names")"},"id":10,"parent":9,"structure":[],"text":"names","range":{"endColumn":10,"endRow":3,"startColumn":5,"startRow":3},"type":"other"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"ref":"ArrayExprSyntax","value":{"text":"ArrayExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"type":"other","text":"InitializerClause","id":11,"parent":8,"range":{"endColumn":40,"endRow":3,"startColumn":11,"startRow":3}},{"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"structure":[],"text":"=","type":"other","range":{"endColumn":12,"endRow":3,"startColumn":11,"startRow":3},"id":12,"parent":11},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftSquare"},{"value":{"text":"[","kind":"leftSquare"},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndElements"},{"ref":"ArrayElementListSyntax","value":{"text":"ArrayElementListSyntax"},"name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedAfterRightSquare"}],"type":"expr","text":"ArrayExpr","id":13,"parent":11,"range":{"endColumn":40,"endRow":3,"startColumn":13,"startRow":3}},{"parent":13,"range":{"endColumn":14,"endRow":3,"startColumn":13,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftSquare"},"type":"other","text":"[","structure":[],"id":14},{"structure":[{"value":{"text":"ArrayElementSyntax"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"type":"collection","text":"ArrayElementList","id":15,"parent":13,"range":{"endColumn":39,"endRow":3,"startColumn":14,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":16,"parent":15,"range":{"endColumn":22,"endRow":3,"startColumn":14,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":17,"parent":16,"range":{"endColumn":21,"endRow":3,"startColumn":14,"startRow":3}},{"range":{"endColumn":15,"endRow":3,"startColumn":14,"startRow":3},"id":18,"type":"other","text":""","parent":17,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"structure":[]},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":19,"parent":17,"range":{"endColumn":20,"endRow":3,"startColumn":15,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Alice","kind":"stringSegment("Alice")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":20,"parent":19,"range":{"endColumn":20,"endRow":3,"startColumn":15,"startRow":3}},{"parent":20,"type":"other","structure":[],"id":21,"range":{"endColumn":20,"endRow":3,"startColumn":15,"startRow":3},"text":"Alice","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Alice")"}},{"text":""","id":22,"parent":17,"type":"other","structure":[],"range":{"endColumn":21,"endRow":3,"startColumn":20,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"}},{"range":{"endColumn":22,"endRow":3,"startColumn":21,"startRow":3},"id":23,"type":"other","structure":[],"parent":16,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":","},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":24,"parent":15,"range":{"endColumn":29,"endRow":3,"startColumn":23,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":25,"parent":24,"range":{"endColumn":28,"endRow":3,"startColumn":23,"startRow":3}},{"parent":25,"id":26,"type":"other","structure":[],"text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"endColumn":24,"endRow":3,"startColumn":23,"startRow":3}},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":27,"parent":25,"range":{"endColumn":27,"endRow":3,"startColumn":24,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Bob","kind":"stringSegment("Bob")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":28,"parent":27,"range":{"endColumn":27,"endRow":3,"startColumn":24,"startRow":3}},{"structure":[],"parent":28,"range":{"endColumn":27,"endRow":3,"startColumn":24,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Bob")"},"text":"Bob","type":"other","id":29},{"structure":[],"parent":25,"range":{"endColumn":28,"endRow":3,"startColumn":27,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":30},{"structure":[],"parent":24,"range":{"endColumn":29,"endRow":3,"startColumn":28,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":31},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":32,"parent":15,"range":{"endColumn":39,"endRow":3,"startColumn":30,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":33,"parent":32,"range":{"endColumn":39,"endRow":3,"startColumn":30,"startRow":3}},{"structure":[],"parent":33,"range":{"endColumn":31,"endRow":3,"startColumn":30,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":34},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":35,"parent":33,"range":{"endColumn":38,"endRow":3,"startColumn":31,"startRow":3}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Charlie","kind":"stringSegment("Charlie")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":36,"parent":35,"range":{"endColumn":38,"endRow":3,"startColumn":31,"startRow":3}},{"structure":[],"parent":36,"range":{"endColumn":38,"endRow":3,"startColumn":31,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Charlie")"},"text":"Charlie","type":"other","id":37},{"structure":[],"parent":33,"range":{"endColumn":39,"endRow":3,"startColumn":38,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":38},{"structure":[],"parent":13,"range":{"endColumn":40,"endRow":3,"startColumn":39,"startRow":3},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightSquare"},"text":"]","type":"other","id":39},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ForStmtSyntax","value":{"text":"ForStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":40,"parent":1,"range":{"endColumn":2,"endRow":6,"startColumn":1,"startRow":4}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeForKeyword"},{"value":{"text":"for","kind":"keyword(SwiftSyntax.Keyword.for)"},"name":"forKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenForKeywordAndTryKeyword"},{"value":{"text":"nil"},"name":"tryKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenTryKeywordAndAwaitKeyword"},{"value":{"text":"nil"},"name":"awaitKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenAwaitKeywordAndCaseKeyword"},{"value":{"text":"nil"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInKeyword"},{"value":{"text":"in","kind":"keyword(SwiftSyntax.Keyword.in)"},"name":"inKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenInKeywordAndSequence"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"sequence"},{"value":{"text":"nil"},"name":"unexpectedBetweenSequenceAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndBody"},{"ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"},"name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"type":"other","text":"ForStmt","id":41,"parent":40,"range":{"endColumn":2,"endRow":6,"startColumn":1,"startRow":4}},{"structure":[],"parent":41,"range":{"endColumn":4,"endRow":4,"startColumn":1,"startRow":4},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.for)"},"text":"for","type":"other","id":42},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"name","kind":"identifier("name")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":43,"parent":41,"range":{"endColumn":9,"endRow":4,"startColumn":5,"startRow":4}},{"structure":[],"parent":43,"range":{"endColumn":9,"endRow":4,"startColumn":5,"startRow":4},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("name")"},"text":"name","type":"other","id":44},{"structure":[],"parent":41,"range":{"endColumn":12,"endRow":4,"startColumn":10,"startRow":4},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.in)"},"text":"in","type":"other","id":45},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"names","kind":"identifier("names")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":46,"parent":41,"range":{"endColumn":18,"endRow":4,"startColumn":13,"startRow":4}},{"structure":[],"parent":46,"range":{"endColumn":18,"endRow":4,"startColumn":13,"startRow":4},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("names")"},"text":"names","type":"other","id":47},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","text":"CodeBlock","id":48,"parent":41,"range":{"endColumn":2,"endRow":6,"startColumn":19,"startRow":4}},{"structure":[],"parent":48,"range":{"endColumn":20,"endRow":4,"startColumn":19,"startRow":4},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"text":"{","type":"other","id":49},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"CodeBlockItemList","id":50,"parent":48,"range":{"endColumn":29,"endRow":5,"startColumn":5,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":51,"parent":50,"range":{"endColumn":29,"endRow":5,"startColumn":5,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":52,"parent":51,"range":{"endColumn":29,"endRow":5,"startColumn":5,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":53,"parent":52,"range":{"endColumn":10,"endRow":5,"startColumn":5,"startRow":5}},{"structure":[],"parent":53,"range":{"endColumn":10,"endRow":5,"startColumn":5,"startRow":5},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":54},{"structure":[],"parent":52,"range":{"endColumn":11,"endRow":5,"startColumn":10,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":55},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":56,"parent":52,"range":{"endColumn":28,"endRow":5,"startColumn":11,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":57,"parent":56,"range":{"endColumn":28,"endRow":5,"startColumn":11,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":58,"parent":57,"range":{"endColumn":28,"endRow":5,"startColumn":11,"startRow":5}},{"structure":[],"parent":58,"range":{"endColumn":12,"endRow":5,"startColumn":11,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":59},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":60,"parent":58,"range":{"endColumn":27,"endRow":5,"startColumn":12,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Hello, ","kind":"stringSegment("Hello, ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":61,"parent":60,"range":{"endColumn":19,"endRow":5,"startColumn":12,"startRow":5}},{"structure":[],"parent":61,"range":{"endColumn":19,"endRow":5,"startColumn":12,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Hello, ")"},"text":"Hello,␣<\/span>","type":"other","id":62},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment","id":63,"parent":60,"range":{"endColumn":26,"endRow":5,"startColumn":19,"startRow":5}},{"structure":[],"parent":63,"range":{"endColumn":20,"endRow":5,"startColumn":19,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"text":"\\","type":"other","id":64},{"structure":[],"parent":63,"range":{"endColumn":21,"endRow":5,"startColumn":20,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":65},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":66,"parent":63,"range":{"endColumn":25,"endRow":5,"startColumn":21,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":67,"parent":66,"range":{"endColumn":25,"endRow":5,"startColumn":21,"startRow":5}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":68,"parent":67,"range":{"endColumn":25,"endRow":5,"startColumn":21,"startRow":5}},{"structure":[],"parent":68,"range":{"endColumn":25,"endRow":5,"startColumn":21,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"text":"name","type":"other","id":69},{"structure":[],"parent":63,"range":{"endColumn":26,"endRow":5,"startColumn":25,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":70},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"!","kind":"stringSegment("!")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":71,"parent":60,"range":{"endColumn":27,"endRow":5,"startColumn":26,"startRow":5}},{"structure":[],"parent":71,"range":{"endColumn":27,"endRow":5,"startColumn":26,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("!")"},"text":"!","type":"other","id":72},{"structure":[],"parent":58,"range":{"endColumn":28,"endRow":5,"startColumn":27,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":73},{"structure":[],"parent":52,"range":{"endColumn":29,"endRow":5,"startColumn":28,"startRow":5},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":74},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":75,"parent":52,"range":{"endColumn":29,"endRow":5,"startColumn":29,"startRow":5}},{"structure":[],"parent":48,"range":{"endColumn":2,"endRow":6,"startColumn":1,"startRow":6},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"text":"}","type":"other","id":76},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":77,"parent":1,"range":{"endColumn":42,"endRow":10,"startColumn":1,"startRow":10}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":78,"parent":77,"range":{"endColumn":42,"endRow":10,"startColumn":1,"startRow":10}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":79,"parent":78,"range":{"endColumn":6,"endRow":10,"startColumn":1,"startRow":10}},{"structure":[],"parent":79,"range":{"endColumn":6,"endRow":10,"startColumn":1,"startRow":10},"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>For-in␣<\/span>with␣<\/span>Enumerated<\/span>↲<\/span>\/\/␣<\/span>For-in␣<\/span>loop␣<\/span>with␣<\/span>enumerated()␣<\/span>to␣<\/span>get␣<\/span>index␣<\/span>and␣<\/span>value<\/span>↲<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":80},{"structure":[],"parent":78,"range":{"endColumn":7,"endRow":10,"startColumn":6,"startRow":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":81},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":82,"parent":78,"range":{"endColumn":41,"endRow":10,"startColumn":7,"startRow":10}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":83,"parent":82,"range":{"endColumn":41,"endRow":10,"startColumn":7,"startRow":10}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":84,"parent":83,"range":{"endColumn":41,"endRow":10,"startColumn":7,"startRow":10}},{"structure":[],"parent":84,"range":{"endColumn":8,"endRow":10,"startColumn":7,"startRow":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":85},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":86,"parent":84,"range":{"endColumn":40,"endRow":10,"startColumn":8,"startRow":10}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"\\n","kind":"stringSegment("\\\\n")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":87,"parent":86,"range":{"endColumn":10,"endRow":10,"startColumn":8,"startRow":10}},{"structure":[],"parent":87,"range":{"endColumn":10,"endRow":10,"startColumn":8,"startRow":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("\\\\n")"},"text":"\\n","type":"other","id":88},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"=== For-in with Enumerated ===","kind":"stringSegment("=== For-in with Enumerated ===")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":89,"parent":86,"range":{"endColumn":40,"endRow":10,"startColumn":10,"startRow":10}},{"structure":[],"parent":89,"range":{"endColumn":40,"endRow":10,"startColumn":10,"startRow":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("=== For-in with Enumerated ===")"},"text":"===␣<\/span>For-in␣<\/span>with␣<\/span>Enumerated␣<\/span>===","type":"other","id":90},{"structure":[],"parent":84,"range":{"endColumn":41,"endRow":10,"startColumn":40,"startRow":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":91},{"structure":[],"parent":78,"range":{"endColumn":42,"endRow":10,"startColumn":41,"startRow":10},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":92},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":93,"parent":78,"range":{"endColumn":42,"endRow":10,"startColumn":42,"startRow":10}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ForStmtSyntax","value":{"text":"ForStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":94,"parent":1,"range":{"endColumn":2,"endRow":13,"startColumn":1,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeForKeyword"},{"value":{"text":"for","kind":"keyword(SwiftSyntax.Keyword.for)"},"name":"forKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenForKeywordAndTryKeyword"},{"value":{"text":"nil"},"name":"tryKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenTryKeywordAndAwaitKeyword"},{"value":{"text":"nil"},"name":"awaitKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenAwaitKeywordAndCaseKeyword"},{"value":{"text":"nil"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndPattern"},{"ref":"TuplePatternSyntax","value":{"text":"TuplePatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInKeyword"},{"value":{"text":"in","kind":"keyword(SwiftSyntax.Keyword.in)"},"name":"inKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenInKeywordAndSequence"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"sequence"},{"value":{"text":"nil"},"name":"unexpectedBetweenSequenceAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndBody"},{"ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"},"name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"type":"other","text":"ForStmt","id":95,"parent":94,"range":{"endColumn":2,"endRow":13,"startColumn":1,"startRow":11}},{"structure":[],"parent":95,"range":{"endColumn":4,"endRow":11,"startColumn":1,"startRow":11},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.for)"},"text":"for","type":"other","id":96},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"ref":"TuplePatternElementListSyntax","value":{"text":"TuplePatternElementListSyntax"},"name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"pattern","text":"TuplePattern","id":97,"parent":95,"range":{"endColumn":18,"endRow":11,"startColumn":5,"startRow":11}},{"structure":[],"parent":97,"range":{"endColumn":6,"endRow":11,"startColumn":5,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":98},{"structure":[{"value":{"text":"TuplePatternElementSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","text":"TuplePatternElementList","id":99,"parent":97,"range":{"endColumn":17,"endRow":11,"startColumn":6,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"TuplePatternElement","id":100,"parent":99,"range":{"endColumn":12,"endRow":11,"startColumn":6,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"index","kind":"identifier("index")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":101,"parent":100,"range":{"endColumn":11,"endRow":11,"startColumn":6,"startRow":11}},{"structure":[],"parent":101,"range":{"endColumn":11,"endRow":11,"startColumn":6,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("index")"},"text":"index","type":"other","id":102},{"structure":[],"parent":100,"range":{"endColumn":12,"endRow":11,"startColumn":11,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":103},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"TuplePatternElement","id":104,"parent":99,"range":{"endColumn":17,"endRow":11,"startColumn":13,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"name","kind":"identifier("name")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":105,"parent":104,"range":{"endColumn":17,"endRow":11,"startColumn":13,"startRow":11}},{"structure":[],"parent":105,"range":{"endColumn":17,"endRow":11,"startColumn":13,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"text":"name","type":"other","id":106},{"structure":[],"parent":97,"range":{"endColumn":18,"endRow":11,"startColumn":17,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightParen"},"text":")","type":"other","id":107},{"structure":[],"parent":95,"range":{"endColumn":21,"endRow":11,"startColumn":19,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.in)"},"text":"in","type":"other","id":108},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":109,"parent":95,"range":{"endColumn":40,"endRow":11,"startColumn":22,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"type":"expr","text":"MemberAccessExpr","id":110,"parent":109,"range":{"endColumn":38,"endRow":11,"startColumn":22,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"names","kind":"identifier("names")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":111,"parent":110,"range":{"endColumn":27,"endRow":11,"startColumn":22,"startRow":11}},{"structure":[],"parent":111,"range":{"endColumn":27,"endRow":11,"startColumn":22,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("names")"},"text":"names","type":"other","id":112},{"structure":[],"parent":110,"range":{"endColumn":28,"endRow":11,"startColumn":27,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"period"},"text":".","type":"other","id":113},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"enumerated","kind":"identifier("enumerated")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":114,"parent":110,"range":{"endColumn":38,"endRow":11,"startColumn":28,"startRow":11}},{"structure":[],"parent":114,"range":{"endColumn":38,"endRow":11,"startColumn":28,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("enumerated")"},"text":"enumerated","type":"other","id":115},{"structure":[],"parent":109,"range":{"endColumn":39,"endRow":11,"startColumn":38,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":116},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":117,"parent":109,"range":{"endColumn":39,"endRow":11,"startColumn":39,"startRow":11}},{"structure":[],"parent":109,"range":{"endColumn":40,"endRow":11,"startColumn":39,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightParen"},"text":")","type":"other","id":118},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":119,"parent":109,"range":{"endColumn":41,"endRow":11,"startColumn":41,"startRow":11}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","text":"CodeBlock","id":120,"parent":95,"range":{"endColumn":2,"endRow":13,"startColumn":41,"startRow":11}},{"structure":[],"parent":120,"range":{"endColumn":42,"endRow":11,"startColumn":41,"startRow":11},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"text":"{","type":"other","id":121},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"CodeBlockItemList","id":122,"parent":120,"range":{"endColumn":44,"endRow":12,"startColumn":5,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":123,"parent":122,"range":{"endColumn":44,"endRow":12,"startColumn":5,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":124,"parent":123,"range":{"endColumn":44,"endRow":12,"startColumn":5,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":125,"parent":124,"range":{"endColumn":10,"endRow":12,"startColumn":5,"startRow":12}},{"structure":[],"parent":125,"range":{"endColumn":10,"endRow":12,"startColumn":5,"startRow":12},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":126},{"structure":[],"parent":124,"range":{"endColumn":11,"endRow":12,"startColumn":10,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":127},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":128,"parent":124,"range":{"endColumn":43,"endRow":12,"startColumn":11,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":129,"parent":128,"range":{"endColumn":43,"endRow":12,"startColumn":11,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":130,"parent":129,"range":{"endColumn":43,"endRow":12,"startColumn":11,"startRow":12}},{"structure":[],"parent":130,"range":{"endColumn":12,"endRow":12,"startColumn":11,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":131},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":132,"parent":130,"range":{"endColumn":42,"endRow":12,"startColumn":12,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Index: ","kind":"stringSegment("Index: ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":133,"parent":132,"range":{"endColumn":19,"endRow":12,"startColumn":12,"startRow":12}},{"structure":[],"parent":133,"range":{"endColumn":19,"endRow":12,"startColumn":12,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Index: ")"},"text":"Index:␣<\/span>","type":"other","id":134},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment","id":135,"parent":132,"range":{"endColumn":27,"endRow":12,"startColumn":19,"startRow":12}},{"structure":[],"parent":135,"range":{"endColumn":20,"endRow":12,"startColumn":19,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"text":"\\","type":"other","id":136},{"structure":[],"parent":135,"range":{"endColumn":21,"endRow":12,"startColumn":20,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":137},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":138,"parent":135,"range":{"endColumn":26,"endRow":12,"startColumn":21,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":139,"parent":138,"range":{"endColumn":26,"endRow":12,"startColumn":21,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"index","kind":"identifier("index")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":140,"parent":139,"range":{"endColumn":26,"endRow":12,"startColumn":21,"startRow":12}},{"structure":[],"parent":140,"range":{"endColumn":26,"endRow":12,"startColumn":21,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("index")"},"text":"index","type":"other","id":141},{"structure":[],"parent":135,"range":{"endColumn":27,"endRow":12,"startColumn":26,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":142},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":", Name: ","kind":"stringSegment(", Name: ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":143,"parent":132,"range":{"endColumn":35,"endRow":12,"startColumn":27,"startRow":12}},{"structure":[],"parent":143,"range":{"endColumn":35,"endRow":12,"startColumn":27,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(", Name: ")"},"text":",␣<\/span>Name:␣<\/span>","type":"other","id":144},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment","id":145,"parent":132,"range":{"endColumn":42,"endRow":12,"startColumn":35,"startRow":12}},{"structure":[],"parent":145,"range":{"endColumn":36,"endRow":12,"startColumn":35,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"text":"\\","type":"other","id":146},{"structure":[],"parent":145,"range":{"endColumn":37,"endRow":12,"startColumn":36,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":147},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":148,"parent":145,"range":{"endColumn":41,"endRow":12,"startColumn":37,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":149,"parent":148,"range":{"endColumn":41,"endRow":12,"startColumn":37,"startRow":12}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":150,"parent":149,"range":{"endColumn":41,"endRow":12,"startColumn":37,"startRow":12}},{"structure":[],"parent":150,"range":{"endColumn":41,"endRow":12,"startColumn":37,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"text":"name","type":"other","id":151},{"structure":[],"parent":145,"range":{"endColumn":42,"endRow":12,"startColumn":41,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":152},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":153,"parent":132,"range":{"endColumn":42,"endRow":12,"startColumn":42,"startRow":12}},{"structure":[],"parent":153,"range":{"endColumn":42,"endRow":12,"startColumn":42,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("")"},"text":"","type":"other","id":154},{"structure":[],"parent":130,"range":{"endColumn":43,"endRow":12,"startColumn":42,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":155},{"structure":[],"parent":124,"range":{"endColumn":44,"endRow":12,"startColumn":43,"startRow":12},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":156},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":157,"parent":124,"range":{"endColumn":44,"endRow":12,"startColumn":44,"startRow":12}},{"structure":[],"parent":120,"range":{"endColumn":2,"endRow":13,"startColumn":1,"startRow":13},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"text":"}","type":"other","id":158},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":159,"parent":1,"range":{"endColumn":44,"endRow":17,"startColumn":1,"startRow":17}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":160,"parent":159,"range":{"endColumn":44,"endRow":17,"startColumn":1,"startRow":17}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":161,"parent":160,"range":{"endColumn":6,"endRow":17,"startColumn":1,"startRow":17}},{"structure":[],"parent":161,"range":{"endColumn":6,"endRow":17,"startColumn":1,"startRow":17},"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>For-in␣<\/span>with␣<\/span>Where␣<\/span>Clause<\/span>↲<\/span>\/\/␣<\/span>For-in␣<\/span>loop␣<\/span>with␣<\/span>where␣<\/span>clause<\/span>↲<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":162},{"structure":[],"parent":160,"range":{"endColumn":7,"endRow":17,"startColumn":6,"startRow":17},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":163},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":164,"parent":160,"range":{"endColumn":43,"endRow":17,"startColumn":7,"startRow":17}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":165,"parent":164,"range":{"endColumn":43,"endRow":17,"startColumn":7,"startRow":17}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":166,"parent":165,"range":{"endColumn":43,"endRow":17,"startColumn":7,"startRow":17}},{"structure":[],"parent":166,"range":{"endColumn":8,"endRow":17,"startColumn":7,"startRow":17},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":167},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":168,"parent":166,"range":{"endColumn":42,"endRow":17,"startColumn":8,"startRow":17}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"\\n","kind":"stringSegment("\\\\n")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":169,"parent":168,"range":{"endColumn":10,"endRow":17,"startColumn":8,"startRow":17}},{"structure":[],"parent":169,"range":{"endColumn":10,"endRow":17,"startColumn":8,"startRow":17},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("\\\\n")"},"text":"\\n","type":"other","id":170},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"=== For-in with Where Clause ===","kind":"stringSegment("=== For-in with Where Clause ===")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":171,"parent":168,"range":{"endColumn":42,"endRow":17,"startColumn":10,"startRow":17}},{"structure":[],"parent":171,"range":{"endColumn":42,"endRow":17,"startColumn":10,"startRow":17},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("=== For-in with Where Clause ===")"},"text":"===␣<\/span>For-in␣<\/span>with␣<\/span>Where␣<\/span>Clause␣<\/span>===","type":"other","id":172},{"structure":[],"parent":166,"range":{"endColumn":43,"endRow":17,"startColumn":42,"startRow":17},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":173},{"structure":[],"parent":160,"range":{"endColumn":44,"endRow":17,"startColumn":43,"startRow":17},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":174},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":175,"parent":160,"range":{"endColumn":44,"endRow":17,"startColumn":44,"startRow":17}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":176,"parent":1,"range":{"endColumn":46,"endRow":18,"startColumn":1,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"type":"decl","text":"VariableDecl","id":177,"parent":176,"range":{"endColumn":46,"endRow":18,"startColumn":1,"startRow":18}},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"AttributeList","id":178,"parent":177,"range":{"endColumn":44,"endRow":17,"startColumn":44,"startRow":17}},{"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"DeclModifierList","id":179,"parent":177,"range":{"endColumn":44,"endRow":17,"startColumn":44,"startRow":17}},{"structure":[],"parent":177,"range":{"endColumn":4,"endRow":18,"startColumn":1,"startRow":18},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"text":"let","type":"other","id":180},{"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"PatternBindingList","id":181,"parent":177,"range":{"endColumn":46,"endRow":18,"startColumn":5,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"PatternBinding","id":182,"parent":181,"range":{"endColumn":46,"endRow":18,"startColumn":5,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"numbers","kind":"identifier("numbers")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":183,"parent":182,"range":{"endColumn":12,"endRow":18,"startColumn":5,"startRow":18}},{"structure":[],"parent":183,"range":{"endColumn":12,"endRow":18,"startColumn":5,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("numbers")"},"text":"numbers","type":"other","id":184},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"ref":"ArrayExprSyntax","value":{"text":"ArrayExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"type":"other","text":"InitializerClause","id":185,"parent":182,"range":{"endColumn":46,"endRow":18,"startColumn":13,"startRow":18}},{"structure":[],"parent":185,"range":{"endColumn":14,"endRow":18,"startColumn":13,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"text":"=","type":"other","id":186},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftSquare"},{"value":{"text":"[","kind":"leftSquare"},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndElements"},{"ref":"ArrayElementListSyntax","value":{"text":"ArrayElementListSyntax"},"name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedAfterRightSquare"}],"type":"expr","text":"ArrayExpr","id":187,"parent":185,"range":{"endColumn":46,"endRow":18,"startColumn":15,"startRow":18}},{"structure":[],"parent":187,"range":{"endColumn":16,"endRow":18,"startColumn":15,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftSquare"},"text":"[","type":"other","id":188},{"structure":[{"value":{"text":"ArrayElementSyntax"},"name":"Element"},{"value":{"text":"10"},"name":"Count"}],"type":"collection","text":"ArrayElementList","id":189,"parent":187,"range":{"endColumn":45,"endRow":18,"startColumn":16,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":190,"parent":189,"range":{"endColumn":18,"endRow":18,"startColumn":16,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"1","kind":"integerLiteral("1")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":191,"parent":190,"range":{"endColumn":17,"endRow":18,"startColumn":16,"startRow":18}},{"structure":[],"parent":191,"range":{"endColumn":17,"endRow":18,"startColumn":16,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("1")"},"text":"1","type":"other","id":192},{"structure":[],"parent":190,"range":{"endColumn":18,"endRow":18,"startColumn":17,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":193},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":194,"parent":189,"range":{"endColumn":21,"endRow":18,"startColumn":19,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"2","kind":"integerLiteral("2")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":195,"parent":194,"range":{"endColumn":20,"endRow":18,"startColumn":19,"startRow":18}},{"structure":[],"parent":195,"range":{"endColumn":20,"endRow":18,"startColumn":19,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("2")"},"text":"2","type":"other","id":196},{"structure":[],"parent":194,"range":{"endColumn":21,"endRow":18,"startColumn":20,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":197},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":198,"parent":189,"range":{"endColumn":24,"endRow":18,"startColumn":22,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"3","kind":"integerLiteral("3")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":199,"parent":198,"range":{"endColumn":23,"endRow":18,"startColumn":22,"startRow":18}},{"structure":[],"parent":199,"range":{"endColumn":23,"endRow":18,"startColumn":22,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("3")"},"text":"3","type":"other","id":200},{"structure":[],"parent":198,"range":{"endColumn":24,"endRow":18,"startColumn":23,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":201},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":202,"parent":189,"range":{"endColumn":27,"endRow":18,"startColumn":25,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"4","kind":"integerLiteral("4")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":203,"parent":202,"range":{"endColumn":26,"endRow":18,"startColumn":25,"startRow":18}},{"structure":[],"parent":203,"range":{"endColumn":26,"endRow":18,"startColumn":25,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("4")"},"text":"4","type":"other","id":204},{"structure":[],"parent":202,"range":{"endColumn":27,"endRow":18,"startColumn":26,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":205},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":206,"parent":189,"range":{"endColumn":30,"endRow":18,"startColumn":28,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"5","kind":"integerLiteral("5")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":207,"parent":206,"range":{"endColumn":29,"endRow":18,"startColumn":28,"startRow":18}},{"structure":[],"parent":207,"range":{"endColumn":29,"endRow":18,"startColumn":28,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("5")"},"text":"5","type":"other","id":208},{"structure":[],"parent":206,"range":{"endColumn":30,"endRow":18,"startColumn":29,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":209},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":210,"parent":189,"range":{"endColumn":33,"endRow":18,"startColumn":31,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"6","kind":"integerLiteral("6")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":211,"parent":210,"range":{"endColumn":32,"endRow":18,"startColumn":31,"startRow":18}},{"structure":[],"parent":211,"range":{"endColumn":32,"endRow":18,"startColumn":31,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("6")"},"text":"6","type":"other","id":212},{"structure":[],"parent":210,"range":{"endColumn":33,"endRow":18,"startColumn":32,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":213},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":214,"parent":189,"range":{"endColumn":36,"endRow":18,"startColumn":34,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"7","kind":"integerLiteral("7")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":215,"parent":214,"range":{"endColumn":35,"endRow":18,"startColumn":34,"startRow":18}},{"structure":[],"parent":215,"range":{"endColumn":35,"endRow":18,"startColumn":34,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("7")"},"text":"7","type":"other","id":216},{"structure":[],"parent":214,"range":{"endColumn":36,"endRow":18,"startColumn":35,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":217},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":218,"parent":189,"range":{"endColumn":39,"endRow":18,"startColumn":37,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"8","kind":"integerLiteral("8")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":219,"parent":218,"range":{"endColumn":38,"endRow":18,"startColumn":37,"startRow":18}},{"structure":[],"parent":219,"range":{"endColumn":38,"endRow":18,"startColumn":37,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("8")"},"text":"8","type":"other","id":220},{"structure":[],"parent":218,"range":{"endColumn":39,"endRow":18,"startColumn":38,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":221},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":222,"parent":189,"range":{"endColumn":42,"endRow":18,"startColumn":40,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"9","kind":"integerLiteral("9")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":223,"parent":222,"range":{"endColumn":41,"endRow":18,"startColumn":40,"startRow":18}},{"structure":[],"parent":223,"range":{"endColumn":41,"endRow":18,"startColumn":40,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("9")"},"text":"9","type":"other","id":224},{"structure":[],"parent":222,"range":{"endColumn":42,"endRow":18,"startColumn":41,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":225},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ArrayElement","id":226,"parent":189,"range":{"endColumn":45,"endRow":18,"startColumn":43,"startRow":18}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"10","kind":"integerLiteral("10")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":227,"parent":226,"range":{"endColumn":45,"endRow":18,"startColumn":43,"startRow":18}},{"structure":[],"parent":227,"range":{"endColumn":45,"endRow":18,"startColumn":43,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("10")"},"text":"10","type":"other","id":228},{"structure":[],"parent":187,"range":{"endColumn":46,"endRow":18,"startColumn":45,"startRow":18},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightSquare"},"text":"]","type":"other","id":229},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ForStmtSyntax","value":{"text":"ForStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":230,"parent":1,"range":{"endColumn":2,"endRow":21,"startColumn":1,"startRow":19}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeForKeyword"},{"value":{"text":"for","kind":"keyword(SwiftSyntax.Keyword.for)"},"name":"forKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenForKeywordAndTryKeyword"},{"value":{"text":"nil"},"name":"tryKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenTryKeywordAndAwaitKeyword"},{"value":{"text":"nil"},"name":"awaitKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenAwaitKeywordAndCaseKeyword"},{"value":{"text":"nil"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInKeyword"},{"value":{"text":"in","kind":"keyword(SwiftSyntax.Keyword.in)"},"name":"inKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenInKeywordAndSequence"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"sequence"},{"value":{"text":"nil"},"name":"unexpectedBetweenSequenceAndWhereClause"},{"ref":"WhereClauseSyntax","value":{"text":"WhereClauseSyntax"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndBody"},{"ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"},"name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"type":"other","text":"ForStmt","id":231,"parent":230,"range":{"endColumn":2,"endRow":21,"startColumn":1,"startRow":19}},{"structure":[],"parent":231,"range":{"endColumn":4,"endRow":19,"startColumn":1,"startRow":19},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.for)"},"text":"for","type":"other","id":232},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"number","kind":"identifier("number")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":233,"parent":231,"range":{"endColumn":11,"endRow":19,"startColumn":5,"startRow":19}},{"structure":[],"parent":233,"range":{"endColumn":11,"endRow":19,"startColumn":5,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("number")"},"text":"number","type":"other","id":234},{"structure":[],"parent":231,"range":{"endColumn":14,"endRow":19,"startColumn":12,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.in)"},"text":"in","type":"other","id":235},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"numbers","kind":"identifier("numbers")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":236,"parent":231,"range":{"endColumn":22,"endRow":19,"startColumn":15,"startRow":19}},{"structure":[],"parent":236,"range":{"endColumn":22,"endRow":19,"startColumn":15,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("numbers")"},"text":"numbers","type":"other","id":237},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeWhereKeyword"},{"value":{"text":"where","kind":"keyword(SwiftSyntax.Keyword.where)"},"name":"whereKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereKeywordAndCondition"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"condition"},{"value":{"text":"nil"},"name":"unexpectedAfterCondition"}],"type":"other","text":"WhereClause","id":238,"parent":231,"range":{"endColumn":44,"endRow":19,"startColumn":23,"startRow":19}},{"structure":[],"parent":238,"range":{"endColumn":28,"endRow":19,"startColumn":23,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.where)"},"text":"where","type":"other","id":239},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"type":"expr","text":"InfixOperatorExpr","id":240,"parent":238,"range":{"endColumn":44,"endRow":19,"startColumn":29,"startRow":19}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"type":"expr","text":"InfixOperatorExpr","id":241,"parent":240,"range":{"endColumn":39,"endRow":19,"startColumn":29,"startRow":19}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"number","kind":"identifier("number")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":242,"parent":241,"range":{"endColumn":35,"endRow":19,"startColumn":29,"startRow":19}},{"structure":[],"parent":242,"range":{"endColumn":35,"endRow":19,"startColumn":29,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("number")"},"text":"number","type":"other","id":243},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"text":"%","kind":"binaryOperator("%")"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"type":"expr","text":"BinaryOperatorExpr","id":244,"parent":241,"range":{"endColumn":37,"endRow":19,"startColumn":36,"startRow":19}},{"structure":[],"parent":244,"range":{"endColumn":37,"endRow":19,"startColumn":36,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"binaryOperator("%")"},"text":"%","type":"other","id":245},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"2","kind":"integerLiteral("2")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":246,"parent":241,"range":{"endColumn":39,"endRow":19,"startColumn":38,"startRow":19}},{"structure":[],"parent":246,"range":{"endColumn":39,"endRow":19,"startColumn":38,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"integerLiteral("2")"},"text":"2","type":"other","id":247},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"text":"==","kind":"binaryOperator("==")"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"type":"expr","text":"BinaryOperatorExpr","id":248,"parent":240,"range":{"endColumn":42,"endRow":19,"startColumn":40,"startRow":19}},{"structure":[],"parent":248,"range":{"endColumn":42,"endRow":19,"startColumn":40,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"binaryOperator("==")"},"text":"==","type":"other","id":249},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"0","kind":"integerLiteral("0")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":250,"parent":240,"range":{"endColumn":44,"endRow":19,"startColumn":43,"startRow":19}},{"structure":[],"parent":250,"range":{"endColumn":44,"endRow":19,"startColumn":43,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"integerLiteral("0")"},"text":"0","type":"other","id":251},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","text":"CodeBlock","id":252,"parent":231,"range":{"endColumn":2,"endRow":21,"startColumn":45,"startRow":19}},{"structure":[],"parent":252,"range":{"endColumn":46,"endRow":19,"startColumn":45,"startRow":19},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"text":"{","type":"other","id":253},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"CodeBlockItemList","id":254,"parent":252,"range":{"endColumn":36,"endRow":20,"startColumn":5,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":255,"parent":254,"range":{"endColumn":36,"endRow":20,"startColumn":5,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":256,"parent":255,"range":{"endColumn":36,"endRow":20,"startColumn":5,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":257,"parent":256,"range":{"endColumn":10,"endRow":20,"startColumn":5,"startRow":20}},{"structure":[],"parent":257,"range":{"endColumn":10,"endRow":20,"startColumn":5,"startRow":20},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":258},{"structure":[],"parent":256,"range":{"endColumn":11,"endRow":20,"startColumn":10,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":259},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":260,"parent":256,"range":{"endColumn":35,"endRow":20,"startColumn":11,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":261,"parent":260,"range":{"endColumn":35,"endRow":20,"startColumn":11,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":262,"parent":261,"range":{"endColumn":35,"endRow":20,"startColumn":11,"startRow":20}},{"structure":[],"parent":262,"range":{"endColumn":12,"endRow":20,"startColumn":11,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":263},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":264,"parent":262,"range":{"endColumn":34,"endRow":20,"startColumn":12,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Even number: ","kind":"stringSegment("Even number: ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":265,"parent":264,"range":{"endColumn":25,"endRow":20,"startColumn":12,"startRow":20}},{"structure":[],"parent":265,"range":{"endColumn":25,"endRow":20,"startColumn":12,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Even number: ")"},"text":"Even␣<\/span>number:␣<\/span>","type":"other","id":266},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment","id":267,"parent":264,"range":{"endColumn":34,"endRow":20,"startColumn":25,"startRow":20}},{"structure":[],"parent":267,"range":{"endColumn":26,"endRow":20,"startColumn":25,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"text":"\\","type":"other","id":268},{"structure":[],"parent":267,"range":{"endColumn":27,"endRow":20,"startColumn":26,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":269},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":270,"parent":267,"range":{"endColumn":33,"endRow":20,"startColumn":27,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":271,"parent":270,"range":{"endColumn":33,"endRow":20,"startColumn":27,"startRow":20}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"number","kind":"identifier("number")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":272,"parent":271,"range":{"endColumn":33,"endRow":20,"startColumn":27,"startRow":20}},{"structure":[],"parent":272,"range":{"endColumn":33,"endRow":20,"startColumn":27,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("number")"},"text":"number","type":"other","id":273},{"structure":[],"parent":267,"range":{"endColumn":34,"endRow":20,"startColumn":33,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":274},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":275,"parent":264,"range":{"endColumn":34,"endRow":20,"startColumn":34,"startRow":20}},{"structure":[],"parent":275,"range":{"endColumn":34,"endRow":20,"startColumn":34,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("")"},"text":"","type":"other","id":276},{"structure":[],"parent":262,"range":{"endColumn":35,"endRow":20,"startColumn":34,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":277},{"structure":[],"parent":256,"range":{"endColumn":36,"endRow":20,"startColumn":35,"startRow":20},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":278},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":279,"parent":256,"range":{"endColumn":36,"endRow":20,"startColumn":36,"startRow":20}},{"structure":[],"parent":252,"range":{"endColumn":2,"endRow":21,"startColumn":1,"startRow":21},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"text":"}","type":"other","id":280},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":281,"parent":1,"range":{"endColumn":42,"endRow":25,"startColumn":1,"startRow":25}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":282,"parent":281,"range":{"endColumn":42,"endRow":25,"startColumn":1,"startRow":25}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":283,"parent":282,"range":{"endColumn":6,"endRow":25,"startColumn":1,"startRow":25}},{"structure":[],"parent":283,"range":{"endColumn":6,"endRow":25,"startColumn":1,"startRow":25},"token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>For-in␣<\/span>with␣<\/span>Dictionary<\/span>↲<\/span>\/\/␣<\/span>For-in␣<\/span>loop␣<\/span>over␣<\/span>dictionary<\/span>↲<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":284},{"structure":[],"parent":282,"range":{"endColumn":7,"endRow":25,"startColumn":6,"startRow":25},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":285},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":286,"parent":282,"range":{"endColumn":41,"endRow":25,"startColumn":7,"startRow":25}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":287,"parent":286,"range":{"endColumn":41,"endRow":25,"startColumn":7,"startRow":25}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":288,"parent":287,"range":{"endColumn":41,"endRow":25,"startColumn":7,"startRow":25}},{"structure":[],"parent":288,"range":{"endColumn":8,"endRow":25,"startColumn":7,"startRow":25},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":289},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":290,"parent":288,"range":{"endColumn":40,"endRow":25,"startColumn":8,"startRow":25}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"\\n","kind":"stringSegment("\\\\n")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":291,"parent":290,"range":{"endColumn":10,"endRow":25,"startColumn":8,"startRow":25}},{"structure":[],"parent":291,"range":{"endColumn":10,"endRow":25,"startColumn":8,"startRow":25},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("\\\\n")"},"text":"\\n","type":"other","id":292},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"=== For-in with Dictionary ===","kind":"stringSegment("=== For-in with Dictionary ===")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":293,"parent":290,"range":{"endColumn":40,"endRow":25,"startColumn":10,"startRow":25}},{"structure":[],"parent":293,"range":{"endColumn":40,"endRow":25,"startColumn":10,"startRow":25},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("=== For-in with Dictionary ===")"},"text":"===␣<\/span>For-in␣<\/span>with␣<\/span>Dictionary␣<\/span>===","type":"other","id":294},{"structure":[],"parent":288,"range":{"endColumn":41,"endRow":25,"startColumn":40,"startRow":25},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":295},{"structure":[],"parent":282,"range":{"endColumn":42,"endRow":25,"startColumn":41,"startRow":25},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":296},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":297,"parent":282,"range":{"endColumn":42,"endRow":25,"startColumn":42,"startRow":25}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":298,"parent":1,"range":{"endColumn":53,"endRow":26,"startColumn":1,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"type":"decl","text":"VariableDecl","id":299,"parent":298,"range":{"endColumn":53,"endRow":26,"startColumn":1,"startRow":26}},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"AttributeList","id":300,"parent":299,"range":{"endColumn":42,"endRow":25,"startColumn":42,"startRow":25}},{"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"DeclModifierList","id":301,"parent":299,"range":{"endColumn":42,"endRow":25,"startColumn":42,"startRow":25}},{"structure":[],"parent":299,"range":{"endColumn":4,"endRow":26,"startColumn":1,"startRow":26},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"text":"let","type":"other","id":302},{"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"PatternBindingList","id":303,"parent":299,"range":{"endColumn":53,"endRow":26,"startColumn":5,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"PatternBinding","id":304,"parent":303,"range":{"endColumn":53,"endRow":26,"startColumn":5,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"scores","kind":"identifier("scores")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":305,"parent":304,"range":{"endColumn":11,"endRow":26,"startColumn":5,"startRow":26}},{"structure":[],"parent":305,"range":{"endColumn":11,"endRow":26,"startColumn":5,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("scores")"},"text":"scores","type":"other","id":306},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"ref":"DictionaryExprSyntax","value":{"text":"DictionaryExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"type":"other","text":"InitializerClause","id":307,"parent":304,"range":{"endColumn":53,"endRow":26,"startColumn":12,"startRow":26}},{"structure":[],"parent":307,"range":{"endColumn":13,"endRow":26,"startColumn":12,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"text":"=","type":"other","id":308},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftSquare"},{"value":{"text":"[","kind":"leftSquare"},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndContent"},{"ref":"DictionaryElementListSyntax","value":{"text":"DictionaryElementListSyntax"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedBetweenContentAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedAfterRightSquare"}],"type":"expr","text":"DictionaryExpr","id":309,"parent":307,"range":{"endColumn":53,"endRow":26,"startColumn":14,"startRow":26}},{"structure":[],"parent":309,"range":{"endColumn":15,"endRow":26,"startColumn":14,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftSquare"},"text":"[","type":"other","id":310},{"structure":[{"value":{"text":"DictionaryElementSyntax"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"type":"collection","text":"DictionaryElementList","id":311,"parent":309,"range":{"endColumn":52,"endRow":26,"startColumn":15,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeKey"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"key"},{"value":{"text":"nil"},"name":"unexpectedBetweenKeyAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndValue"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedBetweenValueAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"DictionaryElement","id":312,"parent":311,"range":{"endColumn":27,"endRow":26,"startColumn":15,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":313,"parent":312,"range":{"endColumn":22,"endRow":26,"startColumn":15,"startRow":26}},{"structure":[],"parent":313,"range":{"endColumn":16,"endRow":26,"startColumn":15,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":314},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":315,"parent":313,"range":{"endColumn":21,"endRow":26,"startColumn":16,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Alice","kind":"stringSegment("Alice")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":316,"parent":315,"range":{"endColumn":21,"endRow":26,"startColumn":16,"startRow":26}},{"structure":[],"parent":316,"range":{"endColumn":21,"endRow":26,"startColumn":16,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Alice")"},"text":"Alice","type":"other","id":317},{"structure":[],"parent":313,"range":{"endColumn":22,"endRow":26,"startColumn":21,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":318},{"structure":[],"parent":312,"range":{"endColumn":23,"endRow":26,"startColumn":22,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"text":":","type":"other","id":319},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"95","kind":"integerLiteral("95")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":320,"parent":312,"range":{"endColumn":26,"endRow":26,"startColumn":24,"startRow":26}},{"structure":[],"parent":320,"range":{"endColumn":26,"endRow":26,"startColumn":24,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("95")"},"text":"95","type":"other","id":321},{"structure":[],"parent":312,"range":{"endColumn":27,"endRow":26,"startColumn":26,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":322},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeKey"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"key"},{"value":{"text":"nil"},"name":"unexpectedBetweenKeyAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndValue"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedBetweenValueAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"DictionaryElement","id":323,"parent":311,"range":{"endColumn":38,"endRow":26,"startColumn":28,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":324,"parent":323,"range":{"endColumn":33,"endRow":26,"startColumn":28,"startRow":26}},{"structure":[],"parent":324,"range":{"endColumn":29,"endRow":26,"startColumn":28,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":325},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":326,"parent":324,"range":{"endColumn":32,"endRow":26,"startColumn":29,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Bob","kind":"stringSegment("Bob")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":327,"parent":326,"range":{"endColumn":32,"endRow":26,"startColumn":29,"startRow":26}},{"structure":[],"parent":327,"range":{"endColumn":32,"endRow":26,"startColumn":29,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Bob")"},"text":"Bob","type":"other","id":328},{"structure":[],"parent":324,"range":{"endColumn":33,"endRow":26,"startColumn":32,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":329},{"structure":[],"parent":323,"range":{"endColumn":34,"endRow":26,"startColumn":33,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"text":":","type":"other","id":330},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"87","kind":"integerLiteral("87")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":331,"parent":323,"range":{"endColumn":37,"endRow":26,"startColumn":35,"startRow":26}},{"structure":[],"parent":331,"range":{"endColumn":37,"endRow":26,"startColumn":35,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("87")"},"text":"87","type":"other","id":332},{"structure":[],"parent":323,"range":{"endColumn":38,"endRow":26,"startColumn":37,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":333},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeKey"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"key"},{"value":{"text":"nil"},"name":"unexpectedBetweenKeyAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndValue"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedBetweenValueAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"DictionaryElement","id":334,"parent":311,"range":{"endColumn":52,"endRow":26,"startColumn":39,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":335,"parent":334,"range":{"endColumn":48,"endRow":26,"startColumn":39,"startRow":26}},{"structure":[],"parent":335,"range":{"endColumn":40,"endRow":26,"startColumn":39,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":336},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":337,"parent":335,"range":{"endColumn":47,"endRow":26,"startColumn":40,"startRow":26}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Charlie","kind":"stringSegment("Charlie")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":338,"parent":337,"range":{"endColumn":47,"endRow":26,"startColumn":40,"startRow":26}},{"structure":[],"parent":338,"range":{"endColumn":47,"endRow":26,"startColumn":40,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Charlie")"},"text":"Charlie","type":"other","id":339},{"structure":[],"parent":335,"range":{"endColumn":48,"endRow":26,"startColumn":47,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":340},{"structure":[],"parent":334,"range":{"endColumn":49,"endRow":26,"startColumn":48,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"text":":","type":"other","id":341},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"92","kind":"integerLiteral("92")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr","text":"IntegerLiteralExpr","id":342,"parent":334,"range":{"endColumn":52,"endRow":26,"startColumn":50,"startRow":26}},{"structure":[],"parent":342,"range":{"endColumn":52,"endRow":26,"startColumn":50,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("92")"},"text":"92","type":"other","id":343},{"structure":[],"parent":309,"range":{"endColumn":53,"endRow":26,"startColumn":52,"startRow":26},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightSquare"},"text":"]","type":"other","id":344},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ForStmtSyntax","value":{"text":"ForStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":345,"parent":1,"range":{"endColumn":2,"endRow":29,"startColumn":1,"startRow":27}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeForKeyword"},{"value":{"text":"for","kind":"keyword(SwiftSyntax.Keyword.for)"},"name":"forKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenForKeywordAndTryKeyword"},{"value":{"text":"nil"},"name":"tryKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenTryKeywordAndAwaitKeyword"},{"value":{"text":"nil"},"name":"awaitKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenAwaitKeywordAndCaseKeyword"},{"value":{"text":"nil"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndPattern"},{"ref":"TuplePatternSyntax","value":{"text":"TuplePatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInKeyword"},{"value":{"text":"in","kind":"keyword(SwiftSyntax.Keyword.in)"},"name":"inKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenInKeywordAndSequence"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"sequence"},{"value":{"text":"nil"},"name":"unexpectedBetweenSequenceAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndBody"},{"ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"},"name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"type":"other","text":"ForStmt","id":346,"parent":345,"range":{"endColumn":2,"endRow":29,"startColumn":1,"startRow":27}},{"structure":[],"parent":346,"range":{"endColumn":4,"endRow":27,"startColumn":1,"startRow":27},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.for)"},"text":"for","type":"other","id":347},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"ref":"TuplePatternElementListSyntax","value":{"text":"TuplePatternElementListSyntax"},"name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"pattern","text":"TuplePattern","id":348,"parent":346,"range":{"endColumn":18,"endRow":27,"startColumn":5,"startRow":27}},{"structure":[],"parent":348,"range":{"endColumn":6,"endRow":27,"startColumn":5,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":349},{"structure":[{"value":{"text":"TuplePatternElementSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","text":"TuplePatternElementList","id":350,"parent":348,"range":{"endColumn":17,"endRow":27,"startColumn":6,"startRow":27}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"TuplePatternElement","id":351,"parent":350,"range":{"endColumn":11,"endRow":27,"startColumn":6,"startRow":27}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"name","kind":"identifier("name")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":352,"parent":351,"range":{"endColumn":10,"endRow":27,"startColumn":6,"startRow":27}},{"structure":[],"parent":352,"range":{"endColumn":10,"endRow":27,"startColumn":6,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"text":"name","type":"other","id":353},{"structure":[],"parent":351,"range":{"endColumn":11,"endRow":27,"startColumn":10,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"text":",","type":"other","id":354},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndPattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"TuplePatternElement","id":355,"parent":350,"range":{"endColumn":17,"endRow":27,"startColumn":12,"startRow":27}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"score","kind":"identifier("score")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"type":"pattern","text":"IdentifierPattern","id":356,"parent":355,"range":{"endColumn":17,"endRow":27,"startColumn":12,"startRow":27}},{"structure":[],"parent":356,"range":{"endColumn":17,"endRow":27,"startColumn":12,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("score")"},"text":"score","type":"other","id":357},{"structure":[],"parent":348,"range":{"endColumn":18,"endRow":27,"startColumn":17,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightParen"},"text":")","type":"other","id":358},{"structure":[],"parent":346,"range":{"endColumn":21,"endRow":27,"startColumn":19,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.in)"},"text":"in","type":"other","id":359},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"scores","kind":"identifier("scores")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":360,"parent":346,"range":{"endColumn":28,"endRow":27,"startColumn":22,"startRow":27}},{"structure":[],"parent":360,"range":{"endColumn":28,"endRow":27,"startColumn":22,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("scores")"},"text":"scores","type":"other","id":361},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","text":"CodeBlock","id":362,"parent":346,"range":{"endColumn":2,"endRow":29,"startColumn":29,"startRow":27}},{"structure":[],"parent":362,"range":{"endColumn":30,"endRow":27,"startColumn":29,"startRow":27},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"text":"{","type":"other","id":363},{"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"CodeBlockItemList","id":364,"parent":362,"range":{"endColumn":31,"endRow":28,"startColumn":5,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","id":365,"parent":364,"range":{"endColumn":31,"endRow":28,"startColumn":5,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"type":"expr","text":"FunctionCallExpr","id":366,"parent":365,"range":{"endColumn":31,"endRow":28,"startColumn":5,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":367,"parent":366,"range":{"endColumn":10,"endRow":28,"startColumn":5,"startRow":28}},{"structure":[],"parent":367,"range":{"endColumn":10,"endRow":28,"startColumn":5,"startRow":28},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"text":"print","type":"other","id":368},{"structure":[],"parent":366,"range":{"endColumn":11,"endRow":28,"startColumn":10,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":369},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":370,"parent":366,"range":{"endColumn":30,"endRow":28,"startColumn":11,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"StringLiteralExprSyntax","value":{"text":"StringLiteralExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":371,"parent":370,"range":{"endColumn":30,"endRow":28,"startColumn":11,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"type":"expr","text":"StringLiteralExpr","id":372,"parent":371,"range":{"endColumn":30,"endRow":28,"startColumn":11,"startRow":28}},{"structure":[],"parent":372,"range":{"endColumn":12,"endRow":28,"startColumn":11,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":373},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"5"},"name":"Count"}],"type":"collection","text":"StringLiteralSegmentList","id":374,"parent":372,"range":{"endColumn":29,"endRow":28,"startColumn":12,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":375,"parent":374,"range":{"endColumn":12,"endRow":28,"startColumn":12,"startRow":28}},{"structure":[],"parent":375,"range":{"endColumn":12,"endRow":28,"startColumn":12,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("")"},"text":"","type":"other","id":376},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment","id":377,"parent":374,"range":{"endColumn":19,"endRow":28,"startColumn":12,"startRow":28}},{"structure":[],"parent":377,"range":{"endColumn":13,"endRow":28,"startColumn":12,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"text":"\\","type":"other","id":378},{"structure":[],"parent":377,"range":{"endColumn":14,"endRow":28,"startColumn":13,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":379},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":380,"parent":377,"range":{"endColumn":18,"endRow":28,"startColumn":14,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":381,"parent":380,"range":{"endColumn":18,"endRow":28,"startColumn":14,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":382,"parent":381,"range":{"endColumn":18,"endRow":28,"startColumn":14,"startRow":28}},{"structure":[],"parent":382,"range":{"endColumn":18,"endRow":28,"startColumn":14,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"text":"name","type":"other","id":383},{"structure":[],"parent":377,"range":{"endColumn":19,"endRow":28,"startColumn":18,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":384},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":": ","kind":"stringSegment(": ")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":385,"parent":374,"range":{"endColumn":21,"endRow":28,"startColumn":19,"startRow":28}},{"structure":[],"parent":385,"range":{"endColumn":21,"endRow":28,"startColumn":19,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(": ")"},"text":":␣<\/span>","type":"other","id":386},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other","text":"ExpressionSegment","id":387,"parent":374,"range":{"endColumn":29,"endRow":28,"startColumn":21,"startRow":28}},{"structure":[],"parent":387,"range":{"endColumn":22,"endRow":28,"startColumn":21,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"text":"\\","type":"other","id":388},{"structure":[],"parent":387,"range":{"endColumn":23,"endRow":28,"startColumn":22,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"text":"(","type":"other","id":389},{"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","text":"LabeledExprList","id":390,"parent":387,"range":{"endColumn":28,"endRow":28,"startColumn":23,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","id":391,"parent":390,"range":{"endColumn":28,"endRow":28,"startColumn":23,"startRow":28}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"score","kind":"identifier("score")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","text":"DeclReferenceExpr","id":392,"parent":391,"range":{"endColumn":28,"endRow":28,"startColumn":23,"startRow":28}},{"structure":[],"parent":392,"range":{"endColumn":28,"endRow":28,"startColumn":23,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("score")"},"text":"score","type":"other","id":393},{"structure":[],"parent":387,"range":{"endColumn":29,"endRow":28,"startColumn":28,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":394},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"","kind":"stringSegment("")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","text":"StringSegment","id":395,"parent":374,"range":{"endColumn":29,"endRow":28,"startColumn":29,"startRow":28}},{"structure":[],"parent":395,"range":{"endColumn":29,"endRow":28,"startColumn":29,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("")"},"text":"","type":"other","id":396},{"structure":[],"parent":372,"range":{"endColumn":30,"endRow":28,"startColumn":29,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"text":""","type":"other","id":397},{"structure":[],"parent":366,"range":{"endColumn":31,"endRow":28,"startColumn":30,"startRow":28},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"text":")","type":"other","id":398},{"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","text":"MultipleTrailingClosureElementList","id":399,"parent":366,"range":{"endColumn":31,"endRow":28,"startColumn":31,"startRow":28}},{"structure":[],"parent":362,"range":{"endColumn":2,"endRow":29,"startColumn":1,"startRow":29},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"text":"}","type":"other","id":400},{"structure":[],"parent":0,"range":{"endColumn":1,"endRow":30,"startColumn":1,"startRow":30},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"endOfFile"},"text":"","type":"other","id":401}] diff --git a/Examples/Remaining/protocols/code.swift b/Examples/Completed/protocols/code.swift similarity index 98% rename from Examples/Remaining/protocols/code.swift rename to Examples/Completed/protocols/code.swift index e0a642d..652ca98 100644 --- a/Examples/Remaining/protocols/code.swift +++ b/Examples/Completed/protocols/code.swift @@ -1,5 +1,3 @@ -import Foundation - // MARK: - Protocol Definition protocol Vehicle { var numberOfWheels: Int { get } diff --git a/Examples/Completed/protocols/dsl.swift b/Examples/Completed/protocols/dsl.swift new file mode 100644 index 0000000..bd1794f --- /dev/null +++ b/Examples/Completed/protocols/dsl.swift @@ -0,0 +1,106 @@ +import SyntaxKit + +// Generate and print the code +let generatedCode = Group { + // MARK: - Protocol Definition + Protocol("Vehicle") { + PropertyRequirement("numberOfWheels", type: "Int", access: .get) + PropertyRequirement("brand", type: "String", access: .get) + FunctionRequirement("start") + FunctionRequirement("stop") + } + + // MARK: - Protocol Extension + Extension("Vehicle") { + Function("start") { + Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) vehicle...\"") + } + } + + Function("stop") { + Call("print") { + ParameterExp(name: "", value: "\"Stopping \\(brand) vehicle...\"") + } + } + } + + // MARK: - Protocol Composition + Protocol("Electric") { + PropertyRequirement("batteryLevel", type: "Double", access: .getSet) + FunctionRequirement("charge") + } + + // MARK: - Concrete Types + Struct("Car") { + Variable(.let, name: "numberOfWheels", type: "Int", equals: "4") + Variable(.let, name: "brand", type: "String") + + Function("start") { + Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) car engine...\"") + } + } + }.inherits("Vehicle") + + Struct("ElectricCar") { + Variable(.let, name: "numberOfWheels", type: "Int", equals: "4") + Variable(.let, name: "brand", type: "String") + Variable(.var, name: "batteryLevel", type: "Double") + + Function("charge") { + Call("print") { + ParameterExp(name: "", value: "\"Charging \\(brand) electric car...\"") + } + Assignment("batteryLevel", Literal.float(100.0)) + } + }.inherits("Vehicle") + + // MARK: - Usage Example + VariableDecl(.let, name: "tesla", equals: "ElectricCar(brand: \"Tesla\", batteryLevel: 75.0)") + VariableDecl(.let, name: "toyota", equals: "Car(brand: \"Toyota\")") + + // Demonstrate protocol usage + Function("demonstrateVehicle") { + Parameter(name: "vehicle", type: "Vehicle") + } _: { + Call("print") { + ParameterExp(name: "", value: "\"Vehicle brand: \\(vehicle.brand)\"") + } + Call("print") { + ParameterExp(name: "", value: "\"Number of wheels: \\(vehicle.numberOfWheels)\"") + } + VariableExp("vehicle").call("start") + VariableExp("vehicle").call("stop") + } + + // Demonstrate protocol composition + Function("demonstrateElectricVehicle") { + Parameter(name: "vehicle", type: "Vehicle & Electric") + } _: { + VariableExp("demonstrateVehicle").call("demonstrateVehicle") { + ParameterExp(name: "vehicle", value: "vehicle") + } + Call("print") { + ParameterExp(name: "", value: "\"Battery level: \\(vehicle.batteryLevel)%\"") + } + VariableExp("vehicle").call("charge") + } + + // Test the implementations + Call("print") { + ParameterExp(name: "", value: "\"Testing regular car:\"") + } + VariableExp("demonstrateVehicle").call("demonstrateVehicle") { + ParameterExp(name: "vehicle", value: "toyota") + } + + Call("print") { + ParameterExp(name: "", value: "\"Testing electric car:\"") + } + VariableExp("demonstrateElectricVehicle").call("demonstrateElectricVehicle") { + ParameterExp(name: "vehicle", value: "tesla") + } +} + +print(generatedCode.generateCode()) \ No newline at end of file diff --git a/Examples/Completed/protocols/syntax.json b/Examples/Completed/protocols/syntax.json new file mode 100644 index 0000000..20a467f --- /dev/null +++ b/Examples/Completed/protocols/syntax.json @@ -0,0 +1 @@ +[{"text":"SourceFile","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeShebang"},{"value":{"text":"nil"},"name":"shebang"},{"value":{"text":"nil"},"name":"unexpectedBetweenShebangAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndEndOfFileToken"},{"value":{"kind":"endOfFile","text":""},"name":"endOfFileToken"},{"value":{"text":"nil"},"name":"unexpectedAfterEndOfFileToken"}],"id":0,"range":{"endRow":74,"startColumn":1,"endColumn":1,"startRow":1},"type":"other"},{"text":"CodeBlockItemList","parent":0,"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"14"},"name":"Count"}],"id":1,"range":{"endRow":73,"startColumn":1,"endColumn":34,"startRow":1},"type":"collection"},{"text":"CodeBlockItem","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ImportDeclSyntax"},"ref":"ImportDeclSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":2,"range":{"endRow":1,"startColumn":1,"endColumn":18,"startRow":1},"type":"other"},{"text":"ImportDecl","parent":2,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndImportKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.import)","text":"import"},"name":"importKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenImportKeywordAndImportKindSpecifier"},{"value":{"text":"nil"},"name":"importKindSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenImportKindSpecifierAndPath"},{"value":{"text":"ImportPathComponentListSyntax"},"ref":"ImportPathComponentListSyntax","name":"path"},{"value":{"text":"nil"},"name":"unexpectedAfterPath"}],"id":3,"range":{"endRow":1,"startColumn":1,"endColumn":18,"startRow":1},"type":"decl"},{"text":"AttributeList","parent":3,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":4,"range":{"endRow":1,"startColumn":1,"endColumn":1,"startRow":1},"type":"collection"},{"text":"DeclModifierList","parent":3,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":5,"range":{"endRow":1,"startColumn":1,"endColumn":1,"startRow":1},"type":"collection"},{"range":{"endRow":1,"startColumn":1,"endColumn":7,"startRow":1},"parent":3,"text":"import","id":6,"structure":[],"type":"other","token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.import)","trailingTrivia":"␣<\/span>"}},{"text":"ImportPathComponentList","parent":3,"structure":[{"value":{"text":"ImportPathComponentSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":7,"range":{"endRow":1,"startColumn":8,"endColumn":18,"startRow":1},"type":"collection"},{"text":"ImportPathComponent","parent":7,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("Foundation")","text":"Foundation"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndTrailingPeriod"},{"value":{"text":"nil"},"name":"trailingPeriod"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingPeriod"}],"id":8,"range":{"endRow":1,"startColumn":8,"endColumn":18,"startRow":1},"type":"other"},{"text":"Foundation","parent":8,"structure":[],"id":9,"type":"other","range":{"endRow":1,"startColumn":8,"endColumn":18,"startRow":1},"token":{"leadingTrivia":"","kind":"identifier("Foundation")","trailingTrivia":""}},{"text":"CodeBlockItem","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ProtocolDeclSyntax"},"ref":"ProtocolDeclSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":10,"range":{"endRow":9,"startColumn":1,"endColumn":2,"startRow":4},"type":"other"},{"text":"ProtocolDecl","parent":10,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndProtocolKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.protocol)","text":"protocol"},"name":"protocolKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenProtocolKeywordAndName"},{"value":{"kind":"identifier("Vehicle")","text":"Vehicle"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndPrimaryAssociatedTypeClause"},{"value":{"text":"nil"},"name":"primaryAssociatedTypeClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenPrimaryAssociatedTypeClauseAndInheritanceClause"},{"value":{"text":"nil"},"name":"inheritanceClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause"},{"value":{"text":"nil"},"name":"genericWhereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock"},{"value":{"text":"MemberBlockSyntax"},"ref":"MemberBlockSyntax","name":"memberBlock"},{"value":{"text":"nil"},"name":"unexpectedAfterMemberBlock"}],"id":11,"range":{"endRow":9,"startColumn":1,"endColumn":2,"startRow":4},"type":"decl"},{"text":"AttributeList","parent":11,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":12,"range":{"startRow":1,"endRow":1,"endColumn":18,"startColumn":18},"type":"collection"},{"text":"DeclModifierList","parent":11,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":13,"range":{"startRow":1,"endRow":1,"endColumn":18,"startColumn":18},"type":"collection"},{"token":{"kind":"keyword(SwiftSyntax.Keyword.protocol)","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Protocol␣<\/span>Definition<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"id":14,"structure":[],"range":{"startRow":4,"endRow":4,"endColumn":9,"startColumn":1},"text":"protocol","parent":11,"type":"other"},{"token":{"kind":"identifier("Vehicle")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other","id":15,"parent":11,"range":{"startRow":4,"endRow":4,"endColumn":17,"startColumn":10},"structure":[],"text":"Vehicle"},{"text":"MemberBlock","parent":11,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"name":"members","ref":"MemberBlockItemListSyntax","value":{"text":"MemberBlockItemListSyntax"}},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":16,"range":{"startRow":4,"endRow":9,"endColumn":2,"startColumn":18},"type":"other"},{"structure":[],"type":"other","id":17,"parent":16,"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":4,"endRow":4,"endColumn":19,"startColumn":18},"text":"{"},{"text":"MemberBlockItemList","parent":16,"structure":[{"name":"Element","value":{"text":"MemberBlockItemSyntax"}},{"name":"Count","value":{"text":"4"}}],"id":18,"range":{"startRow":5,"endRow":8,"endColumn":16,"startColumn":5},"type":"collection"},{"text":"MemberBlockItem","parent":18,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":19,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":5},"type":"other"},{"text":"VariableDecl","parent":19,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":20,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":20,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":21,"range":{"startRow":4,"endRow":4,"endColumn":19,"startColumn":19},"type":"collection"},{"text":"DeclModifierList","parent":20,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":22,"range":{"startRow":4,"endRow":4,"endColumn":19,"startColumn":19},"type":"collection"},{"text":"var","type":"other","parent":20,"token":{"kind":"keyword(SwiftSyntax.Keyword.var)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"id":23,"structure":[],"range":{"startRow":5,"endRow":5,"endColumn":8,"startColumn":5}},{"text":"PatternBindingList","parent":20,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":24,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":9},"type":"collection"},{"text":"PatternBinding","parent":24,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","ref":"TypeAnnotationSyntax","value":{"text":"TypeAnnotationSyntax"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"nil"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","ref":"AccessorBlockSyntax","value":{"text":"AccessorBlockSyntax"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":25,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":9},"type":"other"},{"text":"IdentifierPattern","parent":25,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"numberOfWheels","kind":"identifier("numberOfWheels")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":26,"range":{"startRow":5,"endRow":5,"endColumn":23,"startColumn":9},"type":"pattern"},{"range":{"startRow":5,"endRow":5,"endColumn":23,"startColumn":9},"text":"numberOfWheels","token":{"kind":"identifier("numberOfWheels")","leadingTrivia":"","trailingTrivia":""},"type":"other","id":27,"parent":26,"structure":[]},{"text":"TypeAnnotation","parent":25,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"id":28,"range":{"startRow":5,"endRow":5,"endColumn":28,"startColumn":23},"type":"other"},{"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":28,"range":{"startRow":5,"endRow":5,"endColumn":24,"startColumn":23},"text":":","structure":[],"type":"other","id":29},{"text":"IdentifierType","parent":28,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Int","kind":"identifier("Int")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":30,"range":{"startRow":5,"endRow":5,"endColumn":28,"startColumn":25},"type":"type"},{"token":{"kind":"identifier("Int")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"range":{"startRow":5,"endRow":5,"endColumn":28,"startColumn":25},"id":31,"type":"other","text":"Int","parent":30},{"text":"AccessorBlock","parent":25,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndAccessors","value":{"text":"nil"}},{"name":"accessors","ref":"AccessorDeclListSyntax","value":{"text":"AccessorDeclListSyntax"}},{"name":"unexpectedBetweenAccessorsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":32,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":29},"type":"other"},{"type":"other","text":"{","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":5,"endRow":5,"endColumn":30,"startColumn":29},"parent":32,"structure":[],"id":33},{"text":"AccessorDeclList","parent":32,"structure":[{"name":"Element","value":{"text":"AccessorDeclSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":34,"range":{"startRow":5,"endRow":5,"endColumn":34,"startColumn":31},"type":"collection"},{"text":"AccessorDecl","parent":34,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifier","value":{"text":"nil"}},{"name":"modifier","value":{"text":"nil"}},{"name":"unexpectedBetweenModifierAndAccessorSpecifier","value":{"text":"nil"}},{"name":"accessorSpecifier","value":{"text":"get","kind":"keyword(SwiftSyntax.Keyword.get)"}},{"name":"unexpectedBetweenAccessorSpecifierAndParameters","value":{"text":"nil"}},{"name":"parameters","value":{"text":"nil"}},{"name":"unexpectedBetweenParametersAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":35,"range":{"startRow":5,"endRow":5,"endColumn":34,"startColumn":31},"type":"decl"},{"text":"AttributeList","parent":35,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":36,"range":{"startRow":5,"endRow":5,"endColumn":31,"startColumn":31},"type":"collection"},{"type":"other","text":"get","token":{"kind":"keyword(SwiftSyntax.Keyword.get)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":5,"endRow":5,"endColumn":34,"startColumn":31},"parent":35,"structure":[],"id":37},{"type":"other","text":"}","token":{"kind":"rightBrace","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":35},"parent":32,"structure":[],"id":38},{"text":"MemberBlockItem","parent":18,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":39,"range":{"startRow":6,"endRow":6,"endColumn":30,"startColumn":5},"type":"other"},{"text":"VariableDecl","parent":39,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":40,"range":{"startRow":6,"endRow":6,"endColumn":30,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":40,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":41,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":36},"type":"collection"},{"text":"DeclModifierList","parent":40,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":42,"range":{"startRow":5,"endRow":5,"endColumn":36,"startColumn":36},"type":"collection"},{"type":"other","text":"var","token":{"kind":"keyword(SwiftSyntax.Keyword.var)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"startRow":6,"endRow":6,"endColumn":8,"startColumn":5},"parent":40,"structure":[],"id":43},{"text":"PatternBindingList","parent":40,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":44,"range":{"startRow":6,"endRow":6,"endColumn":30,"startColumn":9},"type":"collection"},{"text":"PatternBinding","parent":44,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","ref":"TypeAnnotationSyntax","value":{"text":"TypeAnnotationSyntax"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"nil"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","ref":"AccessorBlockSyntax","value":{"text":"AccessorBlockSyntax"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":45,"range":{"startRow":6,"endRow":6,"endColumn":30,"startColumn":9},"type":"other"},{"text":"IdentifierPattern","parent":45,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"brand","kind":"identifier("brand")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":46,"range":{"startRow":6,"endRow":6,"endColumn":14,"startColumn":9},"type":"pattern"},{"type":"other","text":"brand","token":{"kind":"identifier("brand")","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":6,"endRow":6,"endColumn":14,"startColumn":9},"parent":46,"structure":[],"id":47},{"text":"TypeAnnotation","parent":45,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"id":48,"range":{"startRow":6,"endRow":6,"endColumn":22,"startColumn":14},"type":"other"},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":6,"endRow":6,"endColumn":15,"startColumn":14},"parent":48,"structure":[],"id":49},{"text":"IdentifierType","parent":48,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"String","kind":"identifier("String")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":50,"range":{"startRow":6,"endRow":6,"endColumn":22,"startColumn":16},"type":"type"},{"type":"other","text":"String","token":{"kind":"identifier("String")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":6,"endRow":6,"endColumn":22,"startColumn":16},"parent":50,"structure":[],"id":51},{"text":"AccessorBlock","parent":45,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndAccessors","value":{"text":"nil"}},{"name":"accessors","ref":"AccessorDeclListSyntax","value":{"text":"AccessorDeclListSyntax"}},{"name":"unexpectedBetweenAccessorsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":52,"range":{"startRow":6,"endRow":6,"endColumn":30,"startColumn":23},"type":"other"},{"type":"other","text":"{","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":6,"endRow":6,"endColumn":24,"startColumn":23},"parent":52,"structure":[],"id":53},{"text":"AccessorDeclList","parent":52,"structure":[{"name":"Element","value":{"text":"AccessorDeclSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":54,"range":{"startRow":6,"endRow":6,"endColumn":28,"startColumn":25},"type":"collection"},{"text":"AccessorDecl","parent":54,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifier","value":{"text":"nil"}},{"name":"modifier","value":{"text":"nil"}},{"name":"unexpectedBetweenModifierAndAccessorSpecifier","value":{"text":"nil"}},{"name":"accessorSpecifier","value":{"text":"get","kind":"keyword(SwiftSyntax.Keyword.get)"}},{"name":"unexpectedBetweenAccessorSpecifierAndParameters","value":{"text":"nil"}},{"name":"parameters","value":{"text":"nil"}},{"name":"unexpectedBetweenParametersAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":55,"range":{"startRow":6,"endRow":6,"endColumn":28,"startColumn":25},"type":"decl"},{"text":"AttributeList","parent":55,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":56,"range":{"startRow":6,"endRow":6,"endColumn":25,"startColumn":25},"type":"collection"},{"type":"other","text":"get","token":{"kind":"keyword(SwiftSyntax.Keyword.get)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":6,"endRow":6,"endColumn":28,"startColumn":25},"parent":55,"structure":[],"id":57},{"type":"other","text":"}","token":{"kind":"rightBrace","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":6,"endRow":6,"endColumn":30,"startColumn":29},"parent":52,"structure":[],"id":58},{"text":"MemberBlockItem","parent":18,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"FunctionDeclSyntax","value":{"text":"FunctionDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":59,"range":{"startRow":7,"endRow":7,"endColumn":17,"startColumn":5},"type":"other"},{"text":"FunctionDecl","parent":59,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"start","kind":"identifier("start")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"name":"signature","ref":"FunctionSignatureSyntax","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":60,"range":{"startRow":7,"endRow":7,"endColumn":17,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":60,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":61,"range":{"endRow":6,"endColumn":30,"startRow":6,"startColumn":30},"type":"collection"},{"text":"DeclModifierList","parent":60,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":62,"range":{"endRow":6,"endColumn":30,"startRow":6,"startColumn":30},"type":"collection"},{"type":"other","text":"func","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)","trailingTrivia":"␣<\/span>"},"range":{"endRow":7,"endColumn":9,"startRow":7,"startColumn":5},"parent":60,"structure":[],"id":63},{"type":"other","text":"start","token":{"leadingTrivia":"","kind":"identifier("start")","trailingTrivia":""},"range":{"endRow":7,"endColumn":15,"startRow":7,"startColumn":10},"parent":60,"structure":[],"id":64},{"text":"FunctionSignature","parent":60,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"name":"parameterClause","ref":"FunctionParameterClauseSyntax","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":65,"range":{"endRow":7,"endColumn":17,"startRow":7,"startColumn":15},"type":"other"},{"text":"FunctionParameterClause","parent":65,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"name":"parameters","ref":"FunctionParameterListSyntax","value":{"text":"FunctionParameterListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":66,"range":{"endRow":7,"endColumn":17,"startRow":7,"startColumn":15},"type":"other"},{"type":"other","text":"(","token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"range":{"endRow":7,"endColumn":16,"startRow":7,"startColumn":15},"parent":66,"structure":[],"id":67},{"text":"FunctionParameterList","parent":66,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":68,"range":{"endRow":7,"endColumn":16,"startRow":7,"startColumn":16},"type":"collection"},{"type":"other","text":")","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"range":{"endRow":7,"endColumn":17,"startRow":7,"startColumn":16},"parent":66,"structure":[],"id":69},{"text":"MemberBlockItem","parent":18,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"FunctionDeclSyntax","value":{"text":"FunctionDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":70,"range":{"endRow":8,"endColumn":16,"startRow":8,"startColumn":5},"type":"other"},{"text":"FunctionDecl","parent":70,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"stop","kind":"identifier("stop")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"name":"signature","ref":"FunctionSignatureSyntax","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":71,"range":{"endRow":8,"endColumn":16,"startRow":8,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":71,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":72,"range":{"startColumn":17,"endRow":7,"startRow":7,"endColumn":17},"type":"collection"},{"text":"DeclModifierList","parent":71,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":73,"range":{"startColumn":17,"endRow":7,"startRow":7,"endColumn":17},"type":"collection"},{"type":"other","text":"func","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)"},"range":{"startColumn":5,"endRow":8,"startRow":8,"endColumn":9},"parent":71,"structure":[],"id":74},{"type":"other","text":"stop","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("stop")"},"range":{"startColumn":10,"endRow":8,"startRow":8,"endColumn":14},"parent":71,"structure":[],"id":75},{"text":"FunctionSignature","parent":71,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"ref":"FunctionParameterClauseSyntax","name":"parameterClause","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":76,"range":{"startColumn":14,"endRow":8,"startRow":8,"endColumn":16},"type":"other"},{"text":"FunctionParameterClause","parent":76,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"ref":"FunctionParameterListSyntax","name":"parameters","value":{"text":"FunctionParameterListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":77,"range":{"startColumn":14,"endRow":8,"startRow":8,"endColumn":16},"type":"other"},{"type":"other","text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"startColumn":14,"endRow":8,"startRow":8,"endColumn":15},"parent":77,"structure":[],"id":78},{"text":"FunctionParameterList","parent":77,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":79,"range":{"startColumn":15,"endRow":8,"startRow":8,"endColumn":15},"type":"collection"},{"type":"other","text":")","token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"range":{"startColumn":15,"endRow":8,"startRow":8,"endColumn":16},"parent":77,"structure":[],"id":80},{"type":"other","text":"}","token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>","kind":"rightBrace"},"range":{"startColumn":1,"endRow":9,"startRow":9,"endColumn":2},"parent":16,"structure":[],"id":81},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"ExtensionDeclSyntax","name":"item","value":{"text":"ExtensionDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":82,"range":{"startColumn":1,"endRow":20,"startRow":12,"endColumn":2},"type":"other"},{"text":"ExtensionDecl","parent":82,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndExtensionKeyword","value":{"text":"nil"}},{"name":"extensionKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.extension)","text":"extension"}},{"name":"unexpectedBetweenExtensionKeywordAndExtendedType","value":{"text":"nil"}},{"ref":"IdentifierTypeSyntax","name":"extendedType","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenExtendedTypeAndInheritanceClause","value":{"text":"nil"}},{"name":"inheritanceClause","value":{"text":"nil"}},{"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock","value":{"text":"nil"}},{"ref":"MemberBlockSyntax","name":"memberBlock","value":{"text":"MemberBlockSyntax"}},{"name":"unexpectedAfterMemberBlock","value":{"text":"nil"}}],"id":83,"range":{"startColumn":1,"endRow":20,"startRow":12,"endColumn":2},"type":"decl"},{"text":"AttributeList","parent":83,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":84,"range":{"startRow":9,"endColumn":2,"startColumn":2,"endRow":9},"type":"collection"},{"text":"DeclModifierList","parent":83,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":85,"range":{"startRow":9,"endColumn":2,"startColumn":2,"endRow":9},"type":"collection"},{"type":"other","text":"extension","token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Protocol␣<\/span>Extension<\/span>↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.extension)"},"range":{"startRow":12,"endColumn":10,"startColumn":1,"endRow":12},"parent":83,"structure":[],"id":86},{"text":"IdentifierType","parent":83,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("Vehicle")","text":"Vehicle"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":87,"range":{"startRow":12,"endColumn":18,"startColumn":11,"endRow":12},"type":"type"},{"type":"other","text":"Vehicle","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("Vehicle")"},"range":{"startRow":12,"endColumn":18,"startColumn":11,"endRow":12},"parent":87,"structure":[],"id":88},{"text":"MemberBlock","parent":83,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"ref":"MemberBlockItemListSyntax","name":"members","value":{"text":"MemberBlockItemListSyntax"}},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":89,"range":{"startRow":12,"endColumn":2,"startColumn":19,"endRow":20},"type":"other"},{"type":"other","text":"{","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"startRow":12,"endColumn":20,"startColumn":19,"endRow":12},"parent":89,"structure":[],"id":90},{"text":"MemberBlockItemList","parent":89,"structure":[{"name":"Element","value":{"text":"MemberBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":91,"range":{"startRow":13,"endColumn":6,"startColumn":5,"endRow":19},"type":"collection"},{"text":"MemberBlockItem","parent":91,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"ref":"FunctionDeclSyntax","name":"decl","value":{"text":"FunctionDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":92,"range":{"startRow":13,"endColumn":6,"startColumn":5,"endRow":15},"type":"other"},{"text":"FunctionDecl","parent":92,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.func)","text":"func"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("start")","text":"start"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"ref":"FunctionSignatureSyntax","name":"signature","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":93,"range":{"startRow":13,"endColumn":6,"startColumn":5,"endRow":15},"type":"decl"},{"text":"AttributeList","parent":93,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":94,"range":{"endColumn":20,"startColumn":20,"endRow":12,"startRow":12},"type":"collection"},{"text":"DeclModifierList","parent":93,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":95,"range":{"endColumn":20,"startColumn":20,"endRow":12,"startRow":12},"type":"collection"},{"type":"other","text":"func","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)"},"range":{"endColumn":9,"startColumn":5,"endRow":13,"startRow":13},"parent":93,"structure":[],"id":96},{"type":"other","text":"start","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("start")"},"range":{"endColumn":15,"startColumn":10,"endRow":13,"startRow":13},"parent":93,"structure":[],"id":97},{"text":"FunctionSignature","parent":93,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"ref":"FunctionParameterClauseSyntax","name":"parameterClause","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":98,"range":{"endColumn":17,"startColumn":15,"endRow":13,"startRow":13},"type":"other"},{"text":"FunctionParameterClause","parent":98,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"ref":"FunctionParameterListSyntax","name":"parameters","value":{"text":"FunctionParameterListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":99,"range":{"endColumn":17,"startColumn":15,"endRow":13,"startRow":13},"type":"other"},{"type":"other","text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"endColumn":16,"startColumn":15,"endRow":13,"startRow":13},"parent":99,"structure":[],"id":100},{"text":"FunctionParameterList","parent":99,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":101,"range":{"endColumn":16,"startColumn":16,"endRow":13,"startRow":13},"type":"collection"},{"type":"other","text":")","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"rightParen"},"range":{"endColumn":17,"startColumn":16,"endRow":13,"startRow":13},"parent":99,"structure":[],"id":102},{"text":"CodeBlock","parent":93,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":103,"range":{"endColumn":6,"startColumn":18,"endRow":15,"startRow":13},"type":"other"},{"type":"other","text":"{","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftBrace"},"range":{"endColumn":19,"startColumn":18,"endRow":13,"startRow":13},"parent":103,"structure":[],"id":104},{"text":"CodeBlockItemList","parent":103,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":105,"range":{"endColumn":46,"startColumn":9,"endRow":14,"startRow":14},"type":"collection"},{"text":"CodeBlockItem","parent":105,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":106,"range":{"endColumn":46,"startColumn":9,"endRow":14,"startRow":14},"type":"other"},{"text":"FunctionCallExpr","parent":106,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":107,"range":{"endColumn":46,"startColumn":9,"endRow":14,"startRow":14},"type":"expr"},{"text":"DeclReferenceExpr","parent":107,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":108,"range":{"endColumn":14,"startColumn":9,"endRow":14,"startRow":14},"type":"expr"},{"type":"other","text":"print","token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")"},"range":{"endColumn":14,"startColumn":9,"endRow":14,"startRow":14},"parent":108,"structure":[],"id":109},{"type":"other","text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"endColumn":15,"startColumn":14,"endRow":14,"startRow":14},"parent":107,"structure":[],"id":110},{"text":"LabeledExprList","parent":107,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":111,"range":{"endColumn":45,"startColumn":15,"endRow":14,"startRow":14},"type":"collection"},{"text":"LabeledExpr","parent":111,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":112,"range":{"endColumn":45,"startColumn":15,"endRow":14,"startRow":14},"type":"other"},{"text":"StringLiteralExpr","parent":112,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":113,"range":{"endColumn":45,"startColumn":15,"endRow":14,"startRow":14},"type":"expr"},{"type":"other","text":""","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"range":{"endColumn":16,"startColumn":15,"endRow":14,"startRow":14},"parent":113,"structure":[],"id":114},{"text":"StringLiteralSegmentList","parent":113,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"id":115,"range":{"endColumn":44,"startColumn":16,"endRow":14,"startRow":14},"type":"collection"},{"text":"StringSegment","parent":115,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Starting ","kind":"stringSegment("Starting ")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":116,"range":{"endColumn":25,"startColumn":16,"endRow":14,"startRow":14},"type":"other"},{"type":"other","text":"Starting␣<\/span>","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("Starting ")"},"range":{"endColumn":25,"startColumn":16,"endRow":14,"startRow":14},"parent":116,"structure":[],"id":117},{"text":"ExpressionSegment","parent":115,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":118,"range":{"endColumn":33,"startColumn":25,"endRow":14,"startRow":14},"type":"other"},{"type":"other","text":"\\","token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"range":{"endColumn":26,"startColumn":25,"endRow":14,"startRow":14},"parent":118,"structure":[],"id":119},{"type":"other","text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"endColumn":27,"startColumn":26,"endRow":14,"startRow":14},"parent":118,"structure":[],"id":120},{"text":"LabeledExprList","parent":118,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":121,"range":{"endColumn":32,"startColumn":27,"endRow":14,"startRow":14},"type":"collection"},{"text":"LabeledExpr","parent":121,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":122,"range":{"endColumn":32,"startColumn":27,"endRow":14,"startRow":14},"type":"other"},{"text":"DeclReferenceExpr","parent":122,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"brand","kind":"identifier("brand")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":123,"range":{"endColumn":32,"startColumn":27,"endRow":14,"startRow":14},"type":"expr"},{"type":"other","text":"brand","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("brand")"},"range":{"endColumn":32,"startColumn":27,"endRow":14,"startRow":14},"parent":123,"structure":[],"id":124},{"type":"other","text":")","token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"range":{"endColumn":33,"startColumn":32,"endRow":14,"startRow":14},"parent":118,"structure":[],"id":125},{"text":"StringSegment","parent":115,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":" vehicle...","kind":"stringSegment(" vehicle...")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":126,"range":{"endColumn":44,"startColumn":33,"endRow":14,"startRow":14},"type":"other"},{"type":"other","text":"␣<\/span>vehicle...","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment(" vehicle...")"},"range":{"endColumn":44,"startColumn":33,"endRow":14,"startRow":14},"parent":126,"structure":[],"id":127},{"type":"other","text":""","token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"range":{"endColumn":45,"startColumn":44,"endRow":14,"startRow":14},"parent":113,"structure":[],"id":128},{"type":"other","text":")","token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"range":{"endColumn":46,"startColumn":45,"endRow":14,"startRow":14},"parent":107,"structure":[],"id":129},{"text":"MultipleTrailingClosureElementList","parent":107,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":130,"range":{"endColumn":46,"startColumn":46,"endRow":14,"startRow":14},"type":"collection"},{"type":"other","text":"}","token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"rightBrace"},"range":{"endColumn":6,"startColumn":5,"endRow":15,"startRow":15},"parent":103,"structure":[],"id":131},{"text":"MemberBlockItem","parent":91,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"ref":"FunctionDeclSyntax","name":"decl","value":{"text":"FunctionDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":132,"range":{"endColumn":6,"startColumn":5,"endRow":19,"startRow":17},"type":"other"},{"text":"FunctionDecl","parent":132,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"stop","kind":"identifier("stop")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"ref":"FunctionSignatureSyntax","name":"signature","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":133,"range":{"endColumn":6,"startColumn":5,"endRow":19,"startRow":17},"type":"decl"},{"text":"AttributeList","parent":133,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":134,"range":{"endColumn":6,"startRow":15,"startColumn":6,"endRow":15},"type":"collection"},{"text":"DeclModifierList","parent":133,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":135,"range":{"endColumn":6,"startRow":15,"startColumn":6,"endRow":15},"type":"collection"},{"type":"other","text":"func","token":{"leadingTrivia":"↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)"},"range":{"endColumn":9,"startRow":17,"startColumn":5,"endRow":17},"parent":133,"structure":[],"id":136},{"type":"other","text":"stop","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("stop")"},"range":{"endColumn":14,"startRow":17,"startColumn":10,"endRow":17},"parent":133,"structure":[],"id":137},{"text":"FunctionSignature","parent":133,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeParameterClause"},{"value":{"text":"FunctionParameterClauseSyntax"},"ref":"FunctionParameterClauseSyntax","name":"parameterClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers"},{"value":{"text":"nil"},"name":"effectSpecifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenEffectSpecifiersAndReturnClause"},{"value":{"text":"nil"},"name":"returnClause"},{"value":{"text":"nil"},"name":"unexpectedAfterReturnClause"}],"id":138,"range":{"endColumn":16,"startRow":17,"startColumn":14,"endRow":17},"type":"other"},{"text":"FunctionParameterClause","parent":138,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndParameters"},{"value":{"text":"FunctionParameterListSyntax"},"ref":"FunctionParameterListSyntax","name":"parameters"},{"value":{"text":"nil"},"name":"unexpectedBetweenParametersAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":139,"range":{"endColumn":16,"startRow":17,"startColumn":14,"endRow":17},"type":"other"},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endColumn":15,"startRow":17,"startColumn":14,"endRow":17},"parent":139,"structure":[],"id":140},{"text":"FunctionParameterList","parent":139,"structure":[{"value":{"text":"FunctionParameterSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":141,"range":{"endColumn":15,"startRow":17,"startColumn":15,"endRow":17},"type":"collection"},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightParen"},"range":{"endColumn":16,"startRow":17,"startColumn":15,"endRow":17},"parent":139,"structure":[],"id":142},{"text":"CodeBlock","parent":133,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"id":143,"range":{"endColumn":6,"startRow":17,"startColumn":17,"endRow":19},"type":"other"},{"type":"other","text":"{","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"endColumn":18,"startRow":17,"startColumn":17,"endRow":17},"parent":143,"structure":[],"id":144},{"text":"CodeBlockItemList","parent":143,"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":145,"range":{"endColumn":46,"startRow":18,"startColumn":9,"endRow":18},"type":"collection"},{"text":"CodeBlockItem","parent":145,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":146,"range":{"endColumn":46,"startRow":18,"startColumn":9,"endRow":18},"type":"other"},{"text":"FunctionCallExpr","parent":146,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":147,"range":{"endColumn":46,"startRow":18,"startColumn":9,"endRow":18},"type":"expr"},{"text":"DeclReferenceExpr","parent":147,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":148,"range":{"endColumn":14,"startRow":18,"startColumn":9,"endRow":18},"type":"expr"},{"type":"other","text":"print","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"range":{"endColumn":14,"startRow":18,"startColumn":9,"endRow":18},"parent":148,"structure":[],"id":149},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endColumn":15,"startRow":18,"startColumn":14,"endRow":18},"parent":147,"structure":[],"id":150},{"text":"LabeledExprList","parent":147,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":151,"range":{"endColumn":45,"startRow":18,"startColumn":15,"endRow":18},"type":"collection"},{"text":"LabeledExpr","parent":151,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":152,"range":{"endColumn":45,"startRow":18,"startColumn":15,"endRow":18},"type":"other"},{"text":"StringLiteralExpr","parent":152,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"id":153,"range":{"endColumn":45,"startRow":18,"startColumn":15,"endRow":18},"type":"expr"},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"endColumn":16,"startRow":18,"startColumn":15,"endRow":18},"parent":153,"structure":[],"id":154},{"text":"StringLiteralSegmentList","parent":153,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"id":155,"range":{"endColumn":44,"startRow":18,"startColumn":16,"endRow":18},"type":"collection"},{"text":"StringSegment","parent":155,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Stopping ")","text":"Stopping "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":156,"range":{"endColumn":25,"startRow":18,"startColumn":16,"endRow":18},"type":"other"},{"type":"other","text":"Stopping␣<\/span>","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Stopping ")"},"range":{"endColumn":25,"startRow":18,"startColumn":16,"endRow":18},"parent":156,"structure":[],"id":157},{"text":"ExpressionSegment","parent":155,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":158,"range":{"endColumn":33,"startRow":18,"startColumn":25,"endRow":18},"type":"other"},{"type":"other","text":"\\","token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"range":{"endColumn":26,"startRow":18,"startColumn":25,"endRow":18},"parent":158,"structure":[],"id":159},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endColumn":27,"startRow":18,"startColumn":26,"endRow":18},"parent":158,"structure":[],"id":160},{"text":"LabeledExprList","parent":158,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":161,"range":{"endColumn":32,"startRow":18,"startColumn":27,"endRow":18},"type":"collection"},{"text":"LabeledExpr","parent":161,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":162,"range":{"endColumn":32,"startRow":18,"startColumn":27,"endRow":18},"type":"other"},{"text":"DeclReferenceExpr","parent":162,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("brand")","text":"brand"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":163,"range":{"endColumn":32,"startRow":18,"startColumn":27,"endRow":18},"type":"expr"},{"type":"other","text":"brand","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("brand")"},"range":{"endColumn":32,"startRow":18,"startColumn":27,"endRow":18},"parent":163,"structure":[],"id":164},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"endColumn":33,"startRow":18,"startColumn":32,"endRow":18},"parent":158,"structure":[],"id":165},{"text":"StringSegment","parent":155,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment(" vehicle...")","text":" vehicle..."},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":166,"range":{"endColumn":44,"startRow":18,"startColumn":33,"endRow":18},"type":"other"},{"type":"other","text":"␣<\/span>vehicle...","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(" vehicle...")"},"range":{"endColumn":44,"startRow":18,"startColumn":33,"endRow":18},"parent":166,"structure":[],"id":167},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"endColumn":45,"startRow":18,"startColumn":44,"endRow":18},"parent":153,"structure":[],"id":168},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"endColumn":46,"startRow":18,"startColumn":45,"endRow":18},"parent":147,"structure":[],"id":169},{"text":"MultipleTrailingClosureElementList","parent":147,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":170,"range":{"endColumn":46,"startRow":18,"startColumn":46,"endRow":18},"type":"collection"},{"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"endColumn":6,"startRow":19,"startColumn":5,"endRow":19},"parent":143,"structure":[],"id":171},{"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"endColumn":2,"startRow":20,"startColumn":1,"endRow":20},"parent":89,"structure":[],"id":172},{"text":"CodeBlockItem","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ProtocolDeclSyntax"},"ref":"ProtocolDeclSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":173,"range":{"endColumn":2,"startRow":23,"startColumn":1,"endRow":26},"type":"other"},{"text":"ProtocolDecl","parent":173,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndProtocolKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.protocol)","text":"protocol"},"name":"protocolKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenProtocolKeywordAndName"},{"value":{"kind":"identifier("Electric")","text":"Electric"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndPrimaryAssociatedTypeClause"},{"value":{"text":"nil"},"name":"primaryAssociatedTypeClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenPrimaryAssociatedTypeClauseAndInheritanceClause"},{"value":{"text":"nil"},"name":"inheritanceClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause"},{"value":{"text":"nil"},"name":"genericWhereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock"},{"value":{"text":"MemberBlockSyntax"},"ref":"MemberBlockSyntax","name":"memberBlock"},{"value":{"text":"nil"},"name":"unexpectedAfterMemberBlock"}],"id":174,"range":{"endColumn":2,"startRow":23,"startColumn":1,"endRow":26},"type":"decl"},{"text":"AttributeList","parent":174,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":175,"range":{"endColumn":2,"startColumn":2,"startRow":20,"endRow":20},"type":"collection"},{"text":"DeclModifierList","parent":174,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":176,"range":{"endColumn":2,"startColumn":2,"startRow":20,"endRow":20},"type":"collection"},{"type":"other","text":"protocol","token":{"kind":"keyword(SwiftSyntax.Keyword.protocol)","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Protocol␣<\/span>Composition<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":9,"startColumn":1,"startRow":23,"endRow":23},"parent":174,"structure":[],"id":177},{"type":"other","text":"Electric","token":{"kind":"identifier("Electric")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":18,"startColumn":10,"startRow":23,"endRow":23},"parent":174,"structure":[],"id":178},{"text":"MemberBlock","parent":174,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"ref":"MemberBlockItemListSyntax","name":"members","value":{"text":"MemberBlockItemListSyntax"}},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":179,"range":{"endColumn":2,"startColumn":19,"startRow":23,"endRow":26},"type":"other"},{"type":"other","text":"{","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":20,"startColumn":19,"startRow":23,"endRow":23},"parent":179,"structure":[],"id":180},{"text":"MemberBlockItemList","parent":179,"structure":[{"name":"Element","value":{"text":"MemberBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":181,"range":{"endColumn":18,"startColumn":5,"startRow":24,"endRow":25},"type":"collection"},{"text":"MemberBlockItem","parent":181,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"ref":"VariableDeclSyntax","name":"decl","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":182,"range":{"endColumn":41,"startColumn":5,"startRow":24,"endRow":24},"type":"other"},{"text":"VariableDecl","parent":182,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"ref":"PatternBindingListSyntax","name":"bindings","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":183,"range":{"endColumn":41,"startColumn":5,"startRow":24,"endRow":24},"type":"decl"},{"text":"AttributeList","parent":183,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":184,"range":{"endColumn":20,"startColumn":20,"startRow":23,"endRow":23},"type":"collection"},{"text":"DeclModifierList","parent":183,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":185,"range":{"endColumn":20,"startColumn":20,"startRow":23,"endRow":23},"type":"collection"},{"type":"other","text":"var","token":{"kind":"keyword(SwiftSyntax.Keyword.var)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":8,"startColumn":5,"startRow":24,"endRow":24},"parent":183,"structure":[],"id":186},{"text":"PatternBindingList","parent":183,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":187,"range":{"endColumn":41,"startColumn":9,"startRow":24,"endRow":24},"type":"collection"},{"text":"PatternBinding","parent":187,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"ref":"TypeAnnotationSyntax","name":"typeAnnotation","value":{"text":"TypeAnnotationSyntax"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"nil"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"ref":"AccessorBlockSyntax","name":"accessorBlock","value":{"text":"AccessorBlockSyntax"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":188,"range":{"endColumn":41,"startColumn":9,"startRow":24,"endRow":24},"type":"other"},{"text":"IdentifierPattern","parent":188,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"batteryLevel","kind":"identifier("batteryLevel")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":189,"range":{"endColumn":21,"startColumn":9,"startRow":24,"endRow":24},"type":"pattern"},{"type":"other","text":"batteryLevel","token":{"kind":"identifier("batteryLevel")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":21,"startColumn":9,"startRow":24,"endRow":24},"parent":189,"structure":[],"id":190},{"text":"TypeAnnotation","parent":188,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"ref":"IdentifierTypeSyntax","name":"type","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"id":191,"range":{"endColumn":29,"startColumn":21,"startRow":24,"endRow":24},"type":"other"},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":22,"startColumn":21,"startRow":24,"endRow":24},"parent":191,"structure":[],"id":192},{"text":"IdentifierType","parent":191,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Double","kind":"identifier("Double")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":193,"range":{"endColumn":29,"startColumn":23,"startRow":24,"endRow":24},"type":"type"},{"type":"other","text":"Double","token":{"kind":"identifier("Double")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":29,"startColumn":23,"startRow":24,"endRow":24},"parent":193,"structure":[],"id":194},{"text":"AccessorBlock","parent":188,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndAccessors","value":{"text":"nil"}},{"ref":"AccessorDeclListSyntax","name":"accessors","value":{"text":"AccessorDeclListSyntax"}},{"name":"unexpectedBetweenAccessorsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":195,"range":{"endColumn":41,"startColumn":30,"startRow":24,"endRow":24},"type":"other"},{"type":"other","text":"{","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":31,"startColumn":30,"startRow":24,"endRow":24},"parent":195,"structure":[],"id":196},{"text":"AccessorDeclList","parent":195,"structure":[{"name":"Element","value":{"text":"AccessorDeclSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":197,"range":{"endColumn":39,"startColumn":32,"startRow":24,"endRow":24},"type":"collection"},{"text":"AccessorDecl","parent":197,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifier","value":{"text":"nil"}},{"name":"modifier","value":{"text":"nil"}},{"name":"unexpectedBetweenModifierAndAccessorSpecifier","value":{"text":"nil"}},{"name":"accessorSpecifier","value":{"text":"get","kind":"keyword(SwiftSyntax.Keyword.get)"}},{"name":"unexpectedBetweenAccessorSpecifierAndParameters","value":{"text":"nil"}},{"name":"parameters","value":{"text":"nil"}},{"name":"unexpectedBetweenParametersAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":198,"range":{"endColumn":35,"startColumn":32,"startRow":24,"endRow":24},"type":"decl"},{"text":"AttributeList","parent":198,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":199,"range":{"endColumn":32,"startColumn":32,"startRow":24,"endRow":24},"type":"collection"},{"type":"other","text":"get","token":{"kind":"keyword(SwiftSyntax.Keyword.get)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":35,"startColumn":32,"startRow":24,"endRow":24},"parent":198,"structure":[],"id":200},{"text":"AccessorDecl","parent":197,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifier","value":{"text":"nil"}},{"name":"modifier","value":{"text":"nil"}},{"name":"unexpectedBetweenModifierAndAccessorSpecifier","value":{"text":"nil"}},{"name":"accessorSpecifier","value":{"text":"set","kind":"keyword(SwiftSyntax.Keyword.set)"}},{"name":"unexpectedBetweenAccessorSpecifierAndParameters","value":{"text":"nil"}},{"name":"parameters","value":{"text":"nil"}},{"name":"unexpectedBetweenParametersAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":201,"range":{"endColumn":39,"startColumn":36,"startRow":24,"endRow":24},"type":"decl"},{"text":"AttributeList","parent":201,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":202,"range":{"endColumn":36,"startColumn":36,"startRow":24,"endRow":24},"type":"collection"},{"type":"other","text":"set","token":{"kind":"keyword(SwiftSyntax.Keyword.set)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":39,"startColumn":36,"startRow":24,"endRow":24},"parent":201,"structure":[],"id":203},{"type":"other","text":"}","token":{"kind":"rightBrace","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":41,"startColumn":40,"startRow":24,"endRow":24},"parent":195,"structure":[],"id":204},{"text":"MemberBlockItem","parent":181,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"ref":"FunctionDeclSyntax","name":"decl","value":{"text":"FunctionDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":205,"range":{"endColumn":18,"startColumn":5,"startRow":25,"endRow":25},"type":"other"},{"text":"FunctionDecl","parent":205,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"charge","kind":"identifier("charge")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"ref":"FunctionSignatureSyntax","name":"signature","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"nil"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":206,"range":{"endColumn":18,"startColumn":5,"startRow":25,"endRow":25},"type":"decl"},{"text":"AttributeList","parent":206,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":207,"range":{"endColumn":41,"startRow":24,"startColumn":41,"endRow":24},"type":"collection"},{"text":"DeclModifierList","parent":206,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":208,"range":{"endColumn":41,"startRow":24,"startColumn":41,"endRow":24},"type":"collection"},{"type":"other","text":"func","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"endColumn":9,"startRow":25,"startColumn":5,"endRow":25},"parent":206,"structure":[],"id":209},{"type":"other","text":"charge","token":{"trailingTrivia":"","kind":"identifier("charge")","leadingTrivia":""},"range":{"endColumn":16,"startRow":25,"startColumn":10,"endRow":25},"parent":206,"structure":[],"id":210},{"text":"FunctionSignature","parent":206,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"name":"parameterClause","ref":"FunctionParameterClauseSyntax","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":211,"range":{"endColumn":18,"startRow":25,"startColumn":16,"endRow":25},"type":"other"},{"text":"FunctionParameterClause","parent":211,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"name":"parameters","ref":"FunctionParameterListSyntax","value":{"text":"FunctionParameterListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":212,"range":{"endColumn":18,"startRow":25,"startColumn":16,"endRow":25},"type":"other"},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endColumn":17,"startRow":25,"startColumn":16,"endRow":25},"parent":212,"structure":[],"id":213},{"text":"FunctionParameterList","parent":212,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":214,"range":{"endColumn":17,"startRow":25,"startColumn":17,"endRow":25},"type":"collection"},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endColumn":18,"startRow":25,"startColumn":17,"endRow":25},"parent":212,"structure":[],"id":215},{"type":"other","text":"}","token":{"trailingTrivia":"","kind":"rightBrace","leadingTrivia":"↲<\/span>"},"range":{"endColumn":2,"startRow":26,"startColumn":1,"endRow":26},"parent":179,"structure":[],"id":216},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"StructDeclSyntax","value":{"text":"StructDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":217,"range":{"endColumn":2,"startRow":29,"startColumn":1,"endRow":36},"type":"other"},{"text":"StructDecl","parent":217,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndStructKeyword","value":{"text":"nil"}},{"name":"structKeyword","value":{"text":"struct","kind":"keyword(SwiftSyntax.Keyword.struct)"}},{"name":"unexpectedBetweenStructKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"Car","kind":"identifier("Car")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndInheritanceClause","value":{"text":"nil"}},{"name":"inheritanceClause","ref":"InheritanceClauseSyntax","value":{"text":"InheritanceClauseSyntax"}},{"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock","value":{"text":"nil"}},{"name":"memberBlock","ref":"MemberBlockSyntax","value":{"text":"MemberBlockSyntax"}},{"name":"unexpectedAfterMemberBlock","value":{"text":"nil"}}],"id":218,"range":{"endColumn":2,"startRow":29,"startColumn":1,"endRow":36},"type":"decl"},{"text":"AttributeList","parent":218,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":219,"range":{"endRow":26,"startRow":26,"endColumn":2,"startColumn":2},"type":"collection"},{"text":"DeclModifierList","parent":218,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":220,"range":{"endRow":26,"startRow":26,"endColumn":2,"startColumn":2},"type":"collection"},{"type":"other","text":"struct","token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Concrete␣<\/span>Types<\/span>↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.struct)"},"range":{"endRow":29,"startRow":29,"endColumn":7,"startColumn":1},"parent":218,"structure":[],"id":221},{"type":"other","text":"Car","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("Car")"},"range":{"endRow":29,"startRow":29,"endColumn":11,"startColumn":8},"parent":218,"structure":[],"id":222},{"text":"InheritanceClause","parent":218,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndInheritedTypes","value":{"text":"nil"}},{"name":"inheritedTypes","value":{"text":"InheritedTypeListSyntax"},"ref":"InheritedTypeListSyntax"},{"name":"unexpectedAfterInheritedTypes","value":{"text":"nil"}}],"id":223,"range":{"endRow":29,"startRow":29,"endColumn":20,"startColumn":11},"type":"other"},{"type":"other","text":":","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"range":{"endRow":29,"startRow":29,"endColumn":12,"startColumn":11},"parent":223,"structure":[],"id":224},{"text":"InheritedTypeList","parent":223,"structure":[{"name":"Element","value":{"text":"InheritedTypeSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":225,"range":{"endRow":29,"startRow":29,"endColumn":20,"startColumn":13},"type":"collection"},{"text":"InheritedType","parent":225,"structure":[{"name":"unexpectedBeforeType","value":{"text":"nil"}},{"name":"type","value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax"},{"name":"unexpectedBetweenTypeAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":226,"range":{"endRow":29,"startRow":29,"endColumn":20,"startColumn":13},"type":"other"},{"text":"IdentifierType","parent":226,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Vehicle","kind":"identifier("Vehicle")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":227,"range":{"endRow":29,"startRow":29,"endColumn":20,"startColumn":13},"type":"type"},{"type":"other","text":"Vehicle","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("Vehicle")"},"range":{"endRow":29,"startRow":29,"endColumn":20,"startColumn":13},"parent":227,"structure":[],"id":228},{"text":"MemberBlock","parent":218,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"name":"members","value":{"text":"MemberBlockItemListSyntax"},"ref":"MemberBlockItemListSyntax"},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":229,"range":{"endRow":36,"startRow":29,"endColumn":2,"startColumn":21},"type":"other"},{"type":"other","text":"{","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"endRow":29,"startRow":29,"endColumn":22,"startColumn":21},"parent":229,"structure":[],"id":230},{"text":"MemberBlockItemList","parent":229,"structure":[{"name":"Element","value":{"text":"MemberBlockItemSyntax"}},{"name":"Count","value":{"text":"3"}}],"id":231,"range":{"endRow":35,"startRow":30,"endColumn":6,"startColumn":5},"type":"collection"},{"text":"MemberBlockItem","parent":231,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":232,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":5},"type":"other"},{"text":"VariableDecl","parent":232,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":233,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":233,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":234,"range":{"endRow":29,"startRow":29,"endColumn":22,"startColumn":22},"type":"collection"},{"text":"DeclModifierList","parent":233,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":235,"range":{"endRow":29,"startRow":29,"endColumn":22,"startColumn":22},"type":"collection"},{"type":"other","text":"let","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"range":{"endRow":30,"startRow":30,"endColumn":8,"startColumn":5},"parent":233,"structure":[],"id":236},{"text":"PatternBindingList","parent":233,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":237,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":9},"type":"collection"},{"text":"PatternBinding","parent":237,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"TypeAnnotationSyntax"},"ref":"TypeAnnotationSyntax"},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":238,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":9},"type":"other"},{"text":"IdentifierPattern","parent":238,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"numberOfWheels","kind":"identifier("numberOfWheels")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":239,"range":{"endRow":30,"startRow":30,"endColumn":23,"startColumn":9},"type":"pattern"},{"type":"other","text":"numberOfWheels","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("numberOfWheels")"},"range":{"endRow":30,"startRow":30,"endColumn":23,"startColumn":9},"parent":239,"structure":[],"id":240},{"text":"TypeAnnotation","parent":238,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax"},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"id":241,"range":{"endRow":30,"startRow":30,"endColumn":28,"startColumn":23},"type":"other"},{"type":"other","text":":","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"range":{"endRow":30,"startRow":30,"endColumn":24,"startColumn":23},"parent":241,"structure":[],"id":242},{"text":"IdentifierType","parent":241,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Int","kind":"identifier("Int")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":243,"range":{"endRow":30,"startRow":30,"endColumn":28,"startColumn":25},"type":"type"},{"type":"other","text":"Int","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("Int")"},"range":{"endRow":30,"startRow":30,"endColumn":28,"startColumn":25},"parent":243,"structure":[],"id":244},{"text":"InitializerClause","parent":238,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":245,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":29},"type":"other"},{"type":"other","text":"=","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"range":{"endRow":30,"startRow":30,"endColumn":30,"startColumn":29},"parent":245,"structure":[],"id":246},{"text":"IntegerLiteralExpr","parent":245,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"4","kind":"integerLiteral("4")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":247,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":31},"type":"expr"},{"type":"other","text":"4","token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("4")"},"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":31},"parent":247,"structure":[],"id":248},{"text":"MemberBlockItem","parent":231,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":249,"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":5},"type":"other"},{"text":"VariableDecl","parent":249,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":250,"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":250,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":251,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":32},"type":"collection"},{"text":"DeclModifierList","parent":250,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":252,"range":{"endRow":30,"startRow":30,"endColumn":32,"startColumn":32},"type":"collection"},{"type":"other","text":"let","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"range":{"endRow":31,"startRow":31,"endColumn":8,"startColumn":5},"parent":250,"structure":[],"id":253},{"text":"PatternBindingList","parent":250,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":254,"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":9},"type":"collection"},{"text":"PatternBinding","parent":254,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"TypeAnnotationSyntax"},"ref":"TypeAnnotationSyntax"},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"nil"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":255,"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":9},"type":"other"},{"text":"IdentifierPattern","parent":255,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"brand","kind":"identifier("brand")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":256,"range":{"endRow":31,"startRow":31,"endColumn":14,"startColumn":9},"type":"pattern"},{"type":"other","text":"brand","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("brand")"},"range":{"endRow":31,"startRow":31,"endColumn":14,"startColumn":9},"parent":256,"structure":[],"id":257},{"text":"TypeAnnotation","parent":255,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax"},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"id":258,"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":14},"type":"other"},{"type":"other","text":":","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"range":{"endRow":31,"startRow":31,"endColumn":15,"startColumn":14},"parent":258,"structure":[],"id":259},{"text":"IdentifierType","parent":258,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"String","kind":"identifier("String")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":260,"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":16},"type":"type"},{"type":"other","text":"String","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("String")"},"range":{"endRow":31,"startRow":31,"endColumn":22,"startColumn":16},"parent":260,"structure":[],"id":261},{"text":"MemberBlockItem","parent":231,"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","value":{"text":"FunctionDeclSyntax"},"ref":"FunctionDeclSyntax"},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":262,"range":{"endRow":35,"startRow":33,"endColumn":6,"startColumn":5},"type":"other"},{"text":"FunctionDecl","parent":262,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"start","kind":"identifier("start")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"name":"signature","value":{"text":"FunctionSignatureSyntax"},"ref":"FunctionSignatureSyntax"},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":263,"range":{"endRow":35,"startRow":33,"endColumn":6,"startColumn":5},"type":"decl"},{"text":"AttributeList","parent":263,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":264,"range":{"endRow":31,"startRow":31,"startColumn":22,"endColumn":22},"type":"collection"},{"text":"DeclModifierList","parent":263,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":265,"range":{"endRow":31,"startRow":31,"startColumn":22,"endColumn":22},"type":"collection"},{"type":"other","text":"func","token":{"leadingTrivia":"↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)"},"range":{"endRow":33,"startRow":33,"startColumn":5,"endColumn":9},"parent":263,"structure":[],"id":266},{"type":"other","text":"start","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("start")"},"range":{"endRow":33,"startRow":33,"startColumn":10,"endColumn":15},"parent":263,"structure":[],"id":267},{"text":"FunctionSignature","parent":263,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"name":"parameterClause","value":{"text":"FunctionParameterClauseSyntax"},"ref":"FunctionParameterClauseSyntax"},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":268,"range":{"endRow":33,"startRow":33,"startColumn":15,"endColumn":17},"type":"other"},{"text":"FunctionParameterClause","parent":268,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"name":"parameters","value":{"text":"FunctionParameterListSyntax"},"ref":"FunctionParameterListSyntax"},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":269,"range":{"endRow":33,"startRow":33,"startColumn":15,"endColumn":17},"type":"other"},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endRow":33,"startRow":33,"startColumn":15,"endColumn":16},"parent":269,"structure":[],"id":270},{"text":"FunctionParameterList","parent":269,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":271,"range":{"endRow":33,"startRow":33,"startColumn":16,"endColumn":16},"type":"collection"},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightParen"},"range":{"endRow":33,"startRow":33,"startColumn":16,"endColumn":17},"parent":269,"structure":[],"id":272},{"text":"CodeBlock","parent":263,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":273,"range":{"endRow":35,"startRow":33,"startColumn":18,"endColumn":6},"type":"other"},{"type":"other","text":"{","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"endRow":33,"startRow":33,"startColumn":18,"endColumn":19},"parent":273,"structure":[],"id":274},{"text":"CodeBlockItemList","parent":273,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":275,"range":{"endRow":34,"startRow":34,"startColumn":9,"endColumn":49},"type":"collection"},{"text":"CodeBlockItem","parent":275,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":276,"range":{"endRow":34,"startRow":34,"startColumn":9,"endColumn":49},"type":"other"},{"text":"FunctionCallExpr","parent":276,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":277,"range":{"endRow":34,"startRow":34,"startColumn":9,"endColumn":49},"type":"expr"},{"text":"DeclReferenceExpr","parent":277,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("print")","text":"print"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":278,"range":{"endRow":34,"startRow":34,"startColumn":9,"endColumn":14},"type":"expr"},{"type":"other","text":"print","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"range":{"endRow":34,"startRow":34,"startColumn":9,"endColumn":14},"parent":278,"structure":[],"id":279},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endRow":34,"startRow":34,"startColumn":14,"endColumn":15},"parent":277,"structure":[],"id":280},{"text":"LabeledExprList","parent":277,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":281,"range":{"endRow":34,"startRow":34,"startColumn":15,"endColumn":48},"type":"collection"},{"text":"LabeledExpr","parent":281,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":282,"range":{"endRow":34,"startRow":34,"startColumn":15,"endColumn":48},"type":"other"},{"text":"StringLiteralExpr","parent":282,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":283,"range":{"endRow":34,"startRow":34,"startColumn":15,"endColumn":48},"type":"expr"},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"endRow":34,"startRow":34,"startColumn":15,"endColumn":16},"parent":283,"structure":[],"id":284},{"text":"StringLiteralSegmentList","parent":283,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"id":285,"range":{"endRow":34,"startRow":34,"startColumn":16,"endColumn":47},"type":"collection"},{"text":"StringSegment","parent":285,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("Starting ")","text":"Starting "}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":286,"range":{"endRow":34,"startRow":34,"startColumn":16,"endColumn":25},"type":"other"},{"type":"other","text":"Starting␣<\/span>","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Starting ")"},"range":{"endRow":34,"startRow":34,"startColumn":16,"endColumn":25},"parent":286,"structure":[],"id":287},{"text":"ExpressionSegment","parent":285,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"kind":"backslash","text":"\\"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":288,"range":{"endRow":34,"startRow":34,"startColumn":25,"endColumn":33},"type":"other"},{"type":"other","text":"\\","token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"range":{"endRow":34,"startRow":34,"startColumn":25,"endColumn":26},"parent":288,"structure":[],"id":289},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"endRow":34,"startRow":34,"startColumn":26,"endColumn":27},"parent":288,"structure":[],"id":290},{"text":"LabeledExprList","parent":288,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":291,"range":{"endRow":34,"startRow":34,"startColumn":27,"endColumn":32},"type":"collection"},{"text":"LabeledExpr","parent":291,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":292,"range":{"endRow":34,"startRow":34,"startColumn":27,"endColumn":32},"type":"other"},{"text":"DeclReferenceExpr","parent":292,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("brand")","text":"brand"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":293,"range":{"endRow":34,"startRow":34,"startColumn":27,"endColumn":32},"type":"expr"},{"type":"other","text":"brand","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("brand")"},"range":{"endRow":34,"startRow":34,"startColumn":27,"endColumn":32},"parent":293,"structure":[],"id":294},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"endRow":34,"startRow":34,"startColumn":32,"endColumn":33},"parent":288,"structure":[],"id":295},{"text":"StringSegment","parent":285,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(" car engine...")","text":" car engine..."}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":296,"range":{"endRow":34,"startRow":34,"startColumn":33,"endColumn":47},"type":"other"},{"type":"other","text":"␣<\/span>car␣<\/span>engine...","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(" car engine...")"},"range":{"endRow":34,"startRow":34,"startColumn":33,"endColumn":47},"parent":296,"structure":[],"id":297},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"endRow":34,"startRow":34,"startColumn":47,"endColumn":48},"parent":283,"structure":[],"id":298},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"endRow":34,"startRow":34,"startColumn":48,"endColumn":49},"parent":277,"structure":[],"id":299},{"text":"MultipleTrailingClosureElementList","parent":277,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":300,"range":{"endRow":34,"startRow":34,"startColumn":49,"endColumn":49},"type":"collection"},{"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"endRow":35,"startRow":35,"startColumn":5,"endColumn":6},"parent":273,"structure":[],"id":301},{"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"endRow":36,"startRow":36,"startColumn":1,"endColumn":2},"parent":229,"structure":[],"id":302},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"StructDeclSyntax"},"ref":"StructDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":303,"range":{"endRow":47,"startRow":38,"startColumn":1,"endColumn":2},"type":"other"},{"text":"StructDecl","parent":303,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndStructKeyword","value":{"text":"nil"}},{"name":"structKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.struct)","text":"struct"}},{"name":"unexpectedBetweenStructKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("ElectricCar")","text":"ElectricCar"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndInheritanceClause","value":{"text":"nil"}},{"name":"inheritanceClause","value":{"text":"InheritanceClauseSyntax"},"ref":"InheritanceClauseSyntax"},{"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock","value":{"text":"nil"}},{"name":"memberBlock","value":{"text":"MemberBlockSyntax"},"ref":"MemberBlockSyntax"},{"name":"unexpectedAfterMemberBlock","value":{"text":"nil"}}],"id":304,"range":{"endRow":47,"startRow":38,"startColumn":1,"endColumn":2},"type":"decl"},{"text":"AttributeList","parent":304,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":305,"range":{"endColumn":2,"startColumn":2,"startRow":36,"endRow":36},"type":"collection"},{"text":"DeclModifierList","parent":304,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":306,"range":{"endColumn":2,"startColumn":2,"startRow":36,"endRow":36},"type":"collection"},{"type":"other","text":"struct","token":{"kind":"keyword(SwiftSyntax.Keyword.struct)","leadingTrivia":"↲<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":7,"startColumn":1,"startRow":38,"endRow":38},"parent":304,"structure":[],"id":307},{"type":"other","text":"ElectricCar","token":{"kind":"identifier("ElectricCar")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":19,"startColumn":8,"startRow":38,"endRow":38},"parent":304,"structure":[],"id":308},{"text":"InheritanceClause","parent":304,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndInheritedTypes"},{"value":{"text":"InheritedTypeListSyntax"},"name":"inheritedTypes","ref":"InheritedTypeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterInheritedTypes"}],"id":309,"range":{"endColumn":38,"startColumn":19,"startRow":38,"endRow":38},"type":"other"},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":20,"startColumn":19,"startRow":38,"endRow":38},"parent":309,"structure":[],"id":310},{"text":"InheritedTypeList","parent":309,"structure":[{"value":{"text":"InheritedTypeSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"id":311,"range":{"endColumn":38,"startColumn":21,"startRow":38,"endRow":38},"type":"collection"},{"text":"InheritedType","parent":311,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":312,"range":{"endColumn":29,"startColumn":21,"startRow":38,"endRow":38},"type":"other"},{"text":"IdentifierType","parent":312,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"Vehicle","kind":"identifier("Vehicle")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"id":313,"range":{"endColumn":28,"startColumn":21,"startRow":38,"endRow":38},"type":"type"},{"type":"other","text":"Vehicle","token":{"kind":"identifier("Vehicle")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":28,"startColumn":21,"startRow":38,"endRow":38},"parent":313,"structure":[],"id":314},{"type":"other","text":",","token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":29,"startColumn":28,"startRow":38,"endRow":38},"parent":312,"structure":[],"id":315},{"text":"InheritedType","parent":311,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":316,"range":{"endColumn":38,"startColumn":30,"startRow":38,"endRow":38},"type":"other"},{"text":"IdentifierType","parent":316,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"Electric","kind":"identifier("Electric")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"id":317,"range":{"endColumn":38,"startColumn":30,"startRow":38,"endRow":38},"type":"type"},{"type":"other","text":"Electric","token":{"kind":"identifier("Electric")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":38,"startColumn":30,"startRow":38,"endRow":38},"parent":317,"structure":[],"id":318},{"text":"MemberBlock","parent":304,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndMembers"},{"value":{"text":"MemberBlockItemListSyntax"},"name":"members","ref":"MemberBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenMembersAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"id":319,"range":{"endColumn":2,"startColumn":39,"startRow":38,"endRow":47},"type":"other"},{"type":"other","text":"{","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":40,"startColumn":39,"startRow":38,"endRow":38},"parent":319,"structure":[],"id":320},{"text":"MemberBlockItemList","parent":319,"structure":[{"value":{"text":"MemberBlockItemSyntax"},"name":"Element"},{"value":{"text":"4"},"name":"Count"}],"id":321,"range":{"endColumn":6,"startColumn":5,"startRow":39,"endRow":46},"type":"collection"},{"text":"MemberBlockItem","parent":321,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"VariableDeclSyntax"},"name":"decl","ref":"VariableDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":322,"range":{"endColumn":32,"startColumn":5,"startRow":39,"endRow":39},"type":"other"},{"text":"VariableDecl","parent":322,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"name":"attributes","ref":"AttributeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"name":"modifiers","ref":"DeclModifierListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"name":"bindings","ref":"PatternBindingListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"id":323,"range":{"endColumn":32,"startColumn":5,"startRow":39,"endRow":39},"type":"decl"},{"text":"AttributeList","parent":323,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":324,"range":{"endColumn":40,"startColumn":40,"startRow":38,"endRow":38},"type":"collection"},{"text":"DeclModifierList","parent":323,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":325,"range":{"endColumn":40,"startColumn":40,"startRow":38,"endRow":38},"type":"collection"},{"type":"other","text":"let","token":{"kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":8,"startColumn":5,"startRow":39,"endRow":39},"parent":323,"structure":[],"id":326},{"text":"PatternBindingList","parent":323,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":327,"range":{"endColumn":32,"startColumn":9,"startRow":39,"endRow":39},"type":"collection"},{"text":"PatternBinding","parent":327,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation","ref":"TypeAnnotationSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"name":"initializer","ref":"InitializerClauseSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":328,"range":{"endColumn":32,"startColumn":9,"startRow":39,"endRow":39},"type":"other"},{"text":"IdentifierPattern","parent":328,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"numberOfWheels","kind":"identifier("numberOfWheels")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":329,"range":{"endColumn":23,"startColumn":9,"startRow":39,"endRow":39},"type":"pattern"},{"type":"other","text":"numberOfWheels","token":{"kind":"identifier("numberOfWheels")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":23,"startColumn":9,"startRow":39,"endRow":39},"parent":329,"structure":[],"id":330},{"text":"TypeAnnotation","parent":328,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterType"}],"id":331,"range":{"endColumn":28,"startColumn":23,"startRow":39,"endRow":39},"type":"other"},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":24,"startColumn":23,"startRow":39,"endRow":39},"parent":331,"structure":[],"id":332},{"text":"IdentifierType","parent":331,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"Int","kind":"identifier("Int")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"id":333,"range":{"endColumn":28,"startColumn":25,"startRow":39,"endRow":39},"type":"type"},{"type":"other","text":"Int","token":{"kind":"identifier("Int")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":28,"startColumn":25,"startRow":39,"endRow":39},"parent":333,"structure":[],"id":334},{"text":"InitializerClause","parent":328,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"value","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"id":335,"range":{"endColumn":32,"startColumn":29,"startRow":39,"endRow":39},"type":"other"},{"type":"other","text":"=","token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":30,"startColumn":29,"startRow":39,"endRow":39},"parent":335,"structure":[],"id":336},{"text":"IntegerLiteralExpr","parent":335,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"4","kind":"integerLiteral("4")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"id":337,"range":{"endColumn":32,"startColumn":31,"startRow":39,"endRow":39},"type":"expr"},{"type":"other","text":"4","token":{"kind":"integerLiteral("4")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":32,"startColumn":31,"startRow":39,"endRow":39},"parent":337,"structure":[],"id":338},{"text":"MemberBlockItem","parent":321,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"VariableDeclSyntax"},"name":"decl","ref":"VariableDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":339,"range":{"endColumn":22,"startColumn":5,"startRow":40,"endRow":40},"type":"other"},{"text":"VariableDecl","parent":339,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"name":"attributes","ref":"AttributeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"name":"modifiers","ref":"DeclModifierListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"name":"bindings","ref":"PatternBindingListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"id":340,"range":{"endColumn":22,"startColumn":5,"startRow":40,"endRow":40},"type":"decl"},{"text":"AttributeList","parent":340,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":341,"range":{"endColumn":32,"startColumn":32,"startRow":39,"endRow":39},"type":"collection"},{"text":"DeclModifierList","parent":340,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":342,"range":{"endColumn":32,"startColumn":32,"startRow":39,"endRow":39},"type":"collection"},{"type":"other","text":"let","token":{"kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":8,"startColumn":5,"startRow":40,"endRow":40},"parent":340,"structure":[],"id":343},{"text":"PatternBindingList","parent":340,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":344,"range":{"endColumn":22,"startColumn":9,"startRow":40,"endRow":40},"type":"collection"},{"text":"PatternBinding","parent":344,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation","ref":"TypeAnnotationSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"nil"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":345,"range":{"endColumn":22,"startColumn":9,"startRow":40,"endRow":40},"type":"other"},{"text":"IdentifierPattern","parent":345,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"brand","kind":"identifier("brand")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":346,"range":{"endColumn":14,"startColumn":9,"startRow":40,"endRow":40},"type":"pattern"},{"type":"other","text":"brand","token":{"kind":"identifier("brand")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":14,"startColumn":9,"startRow":40,"endRow":40},"parent":346,"structure":[],"id":347},{"text":"TypeAnnotation","parent":345,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterType"}],"id":348,"range":{"endColumn":22,"startColumn":14,"startRow":40,"endRow":40},"type":"other"},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":15,"startColumn":14,"startRow":40,"endRow":40},"parent":348,"structure":[],"id":349},{"text":"IdentifierType","parent":348,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"String","kind":"identifier("String")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"id":350,"range":{"endColumn":22,"startColumn":16,"startRow":40,"endRow":40},"type":"type"},{"type":"other","text":"String","token":{"kind":"identifier("String")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":22,"startColumn":16,"startRow":40,"endRow":40},"parent":350,"structure":[],"id":351},{"text":"MemberBlockItem","parent":321,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"VariableDeclSyntax"},"name":"decl","ref":"VariableDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":352,"range":{"endColumn":29,"startColumn":5,"startRow":41,"endRow":41},"type":"other"},{"text":"VariableDecl","parent":352,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"name":"attributes","ref":"AttributeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"name":"modifiers","ref":"DeclModifierListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"value":{"text":"PatternBindingListSyntax"},"name":"bindings","ref":"PatternBindingListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"id":353,"range":{"endColumn":29,"startColumn":5,"startRow":41,"endRow":41},"type":"decl"},{"text":"AttributeList","parent":353,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":354,"range":{"endColumn":22,"startColumn":22,"startRow":40,"endRow":40},"type":"collection"},{"text":"DeclModifierList","parent":353,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":355,"range":{"endColumn":22,"startColumn":22,"startRow":40,"endRow":40},"type":"collection"},{"type":"other","text":"var","token":{"kind":"keyword(SwiftSyntax.Keyword.var)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":8,"startColumn":5,"startRow":41,"endRow":41},"parent":353,"structure":[],"id":356},{"text":"PatternBindingList","parent":353,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":357,"range":{"endColumn":29,"startColumn":9,"startRow":41,"endRow":41},"type":"collection"},{"text":"PatternBinding","parent":357,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"name":"pattern","ref":"IdentifierPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation","ref":"TypeAnnotationSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"nil"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":358,"range":{"endColumn":29,"startColumn":9,"startRow":41,"endRow":41},"type":"other"},{"text":"IdentifierPattern","parent":358,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"batteryLevel","kind":"identifier("batteryLevel")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":359,"range":{"endColumn":21,"startColumn":9,"startRow":41,"endRow":41},"type":"pattern"},{"type":"other","text":"batteryLevel","token":{"kind":"identifier("batteryLevel")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":21,"startColumn":9,"startRow":41,"endRow":41},"parent":359,"structure":[],"id":360},{"text":"TypeAnnotation","parent":358,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterType"}],"id":361,"range":{"endColumn":29,"startColumn":21,"startRow":41,"endRow":41},"type":"other"},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":22,"startColumn":21,"startRow":41,"endRow":41},"parent":361,"structure":[],"id":362},{"text":"IdentifierType","parent":361,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"Double","kind":"identifier("Double")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"id":363,"range":{"endColumn":29,"startColumn":23,"startRow":41,"endRow":41},"type":"type"},{"type":"other","text":"Double","token":{"kind":"identifier("Double")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":29,"startColumn":23,"startRow":41,"endRow":41},"parent":363,"structure":[],"id":364},{"text":"MemberBlockItem","parent":321,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"FunctionDeclSyntax"},"name":"decl","ref":"FunctionDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":365,"range":{"endColumn":6,"startColumn":5,"startRow":43,"endRow":46},"type":"other"},{"text":"FunctionDecl","parent":365,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"name":"attributes","ref":"AttributeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"name":"modifiers","ref":"DeclModifierListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndFuncKeyword"},{"value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"},"name":"funcKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenFuncKeywordAndName"},{"value":{"text":"charge","kind":"identifier("charge")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericParameterClause"},{"value":{"text":"nil"},"name":"genericParameterClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenGenericParameterClauseAndSignature"},{"value":{"text":"FunctionSignatureSyntax"},"name":"signature","ref":"FunctionSignatureSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSignatureAndGenericWhereClause"},{"value":{"text":"nil"},"name":"genericWhereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenGenericWhereClauseAndBody"},{"value":{"text":"CodeBlockSyntax"},"name":"body","ref":"CodeBlockSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"id":366,"range":{"endColumn":6,"startColumn":5,"startRow":43,"endRow":46},"type":"decl"},{"text":"AttributeList","parent":366,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":367,"range":{"startRow":41,"startColumn":29,"endColumn":29,"endRow":41},"type":"collection"},{"text":"DeclModifierList","parent":366,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":368,"range":{"startRow":41,"startColumn":29,"endColumn":29,"endRow":41},"type":"collection"},{"type":"other","text":"func","token":{"leadingTrivia":"↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)"},"range":{"startRow":43,"startColumn":5,"endColumn":9,"endRow":43},"parent":366,"structure":[],"id":369},{"type":"other","text":"charge","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("charge")"},"range":{"startRow":43,"startColumn":10,"endColumn":16,"endRow":43},"parent":366,"structure":[],"id":370},{"text":"FunctionSignature","parent":366,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"name":"parameterClause","value":{"text":"FunctionParameterClauseSyntax"},"ref":"FunctionParameterClauseSyntax"},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":371,"range":{"startRow":43,"startColumn":16,"endColumn":18,"endRow":43},"type":"other"},{"text":"FunctionParameterClause","parent":371,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"name":"parameters","value":{"text":"FunctionParameterListSyntax"},"ref":"FunctionParameterListSyntax"},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":372,"range":{"startRow":43,"startColumn":16,"endColumn":18,"endRow":43},"type":"other"},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"startRow":43,"startColumn":16,"endColumn":17,"endRow":43},"parent":372,"structure":[],"id":373},{"text":"FunctionParameterList","parent":372,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":374,"range":{"startRow":43,"startColumn":17,"endColumn":17,"endRow":43},"type":"collection"},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"rightParen"},"range":{"startRow":43,"startColumn":17,"endColumn":18,"endRow":43},"parent":372,"structure":[],"id":375},{"text":"CodeBlock","parent":366,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":376,"range":{"startRow":43,"startColumn":19,"endColumn":6,"endRow":46},"type":"other"},{"type":"other","text":"{","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"startRow":43,"startColumn":19,"endColumn":20,"endRow":43},"parent":376,"structure":[],"id":377},{"text":"CodeBlockItemList","parent":376,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":378,"range":{"startRow":44,"startColumn":9,"endColumn":29,"endRow":45},"type":"collection"},{"text":"CodeBlockItem","parent":378,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":379,"range":{"startRow":44,"startColumn":9,"endColumn":51,"endRow":44},"type":"other"},{"text":"FunctionCallExpr","parent":379,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":380,"range":{"startRow":44,"startColumn":9,"endColumn":51,"endRow":44},"type":"expr"},{"text":"DeclReferenceExpr","parent":380,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":381,"range":{"startRow":44,"startColumn":9,"endColumn":14,"endRow":44},"type":"expr"},{"type":"other","text":"print","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"range":{"startRow":44,"startColumn":9,"endColumn":14,"endRow":44},"parent":381,"structure":[],"id":382},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"startRow":44,"startColumn":14,"endColumn":15,"endRow":44},"parent":380,"structure":[],"id":383},{"text":"LabeledExprList","parent":380,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":384,"range":{"startRow":44,"startColumn":15,"endColumn":50,"endRow":44},"type":"collection"},{"text":"LabeledExpr","parent":384,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":385,"range":{"startRow":44,"startColumn":15,"endColumn":50,"endRow":44},"type":"other"},{"text":"StringLiteralExpr","parent":385,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":386,"range":{"startRow":44,"startColumn":15,"endColumn":50,"endRow":44},"type":"expr"},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":44,"startColumn":15,"endColumn":16,"endRow":44},"parent":386,"structure":[],"id":387},{"text":"StringLiteralSegmentList","parent":386,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"id":388,"range":{"startRow":44,"startColumn":16,"endColumn":49,"endRow":44},"type":"collection"},{"text":"StringSegment","parent":388,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Charging ","kind":"stringSegment("Charging ")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":389,"range":{"startRow":44,"startColumn":16,"endColumn":25,"endRow":44},"type":"other"},{"type":"other","text":"Charging␣<\/span>","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Charging ")"},"range":{"startRow":44,"startColumn":16,"endColumn":25,"endRow":44},"parent":389,"structure":[],"id":390},{"text":"ExpressionSegment","parent":388,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":391,"range":{"startRow":44,"startColumn":25,"endColumn":33,"endRow":44},"type":"other"},{"type":"other","text":"\\","token":{"leadingTrivia":"","trailingTrivia":"","kind":"backslash"},"range":{"startRow":44,"startColumn":25,"endColumn":26,"endRow":44},"parent":391,"structure":[],"id":392},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"startRow":44,"startColumn":26,"endColumn":27,"endRow":44},"parent":391,"structure":[],"id":393},{"text":"LabeledExprList","parent":391,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":394,"range":{"startRow":44,"startColumn":27,"endColumn":32,"endRow":44},"type":"collection"},{"text":"LabeledExpr","parent":394,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":395,"range":{"startRow":44,"startColumn":27,"endColumn":32,"endRow":44},"type":"other"},{"text":"DeclReferenceExpr","parent":395,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"brand","kind":"identifier("brand")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":396,"range":{"startRow":44,"startColumn":27,"endColumn":32,"endRow":44},"type":"expr"},{"type":"other","text":"brand","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("brand")"},"range":{"startRow":44,"startColumn":27,"endColumn":32,"endRow":44},"parent":396,"structure":[],"id":397},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"startRow":44,"startColumn":32,"endColumn":33,"endRow":44},"parent":391,"structure":[],"id":398},{"text":"StringSegment","parent":388,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":" electric car...","kind":"stringSegment(" electric car...")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":399,"range":{"startRow":44,"startColumn":33,"endColumn":49,"endRow":44},"type":"other"},{"type":"other","text":"␣<\/span>electric␣<\/span>car...","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment(" electric car...")"},"range":{"startRow":44,"startColumn":33,"endColumn":49,"endRow":44},"parent":399,"structure":[],"id":400},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":44,"startColumn":49,"endColumn":50,"endRow":44},"parent":386,"structure":[],"id":401},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"startRow":44,"startColumn":50,"endColumn":51,"endRow":44},"parent":380,"structure":[],"id":402},{"text":"MultipleTrailingClosureElementList","parent":380,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":403,"range":{"startRow":44,"startColumn":51,"endColumn":51,"endRow":44},"type":"collection"},{"text":"CodeBlockItem","parent":378,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":404,"range":{"startRow":45,"startColumn":9,"endColumn":29,"endRow":45},"type":"other"},{"text":"InfixOperatorExpr","parent":404,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"AssignmentExprSyntax"},"ref":"AssignmentExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"FloatLiteralExprSyntax"},"ref":"FloatLiteralExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"id":405,"range":{"startRow":45,"startColumn":9,"endColumn":29,"endRow":45},"type":"expr"},{"text":"DeclReferenceExpr","parent":405,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"batteryLevel","kind":"identifier("batteryLevel")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":406,"range":{"startRow":45,"startColumn":9,"endColumn":21,"endRow":45},"type":"expr"},{"type":"other","text":"batteryLevel","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"identifier("batteryLevel")"},"range":{"startRow":45,"startColumn":9,"endColumn":21,"endRow":45},"parent":406,"structure":[],"id":407},{"text":"AssignmentExpr","parent":405,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}],"id":408,"range":{"startRow":45,"startColumn":22,"endColumn":23,"endRow":45},"type":"expr"},{"type":"other","text":"=","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"range":{"startRow":45,"startColumn":22,"endColumn":23,"endRow":45},"parent":408,"structure":[],"id":409},{"text":"FloatLiteralExpr","parent":405,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"100.0","kind":"floatLiteral("100.0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":410,"range":{"startRow":45,"startColumn":24,"endColumn":29,"endRow":45},"type":"expr"},{"type":"other","text":"100.0","token":{"leadingTrivia":"","trailingTrivia":"","kind":"floatLiteral("100.0")"},"range":{"startRow":45,"startColumn":24,"endColumn":29,"endRow":45},"parent":410,"structure":[],"id":411},{"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"startRow":46,"startColumn":5,"endColumn":6,"endRow":46},"parent":376,"structure":[],"id":412},{"type":"other","text":"}","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"startRow":47,"startColumn":1,"endColumn":2,"endRow":47},"parent":319,"structure":[],"id":413},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":414,"range":{"startRow":50,"startColumn":1,"endColumn":60,"endRow":50},"type":"other"},{"text":"VariableDecl","parent":414,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":415,"range":{"startRow":50,"startColumn":1,"endColumn":60,"endRow":50},"type":"decl"},{"text":"AttributeList","parent":415,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":416,"range":{"startRow":47,"startColumn":2,"endColumn":2,"endRow":47},"type":"collection"},{"text":"DeclModifierList","parent":415,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":417,"range":{"startRow":47,"startColumn":2,"endColumn":2,"endRow":47},"type":"collection"},{"type":"other","text":"let","token":{"leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>MARK:␣<\/span>-␣<\/span>Usage␣<\/span>Example<\/span>↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"range":{"startRow":50,"startColumn":1,"endColumn":4,"endRow":50},"parent":415,"structure":[],"id":418},{"text":"PatternBindingList","parent":415,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":419,"range":{"startRow":50,"startColumn":5,"endColumn":60,"endRow":50},"type":"collection"},{"text":"PatternBinding","parent":419,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":420,"range":{"startRow":50,"startColumn":5,"endColumn":60,"endRow":50},"type":"other"},{"text":"IdentifierPattern","parent":420,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"tesla","kind":"identifier("tesla")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":421,"range":{"startRow":50,"startColumn":5,"endColumn":10,"endRow":50},"type":"pattern"},{"type":"other","text":"tesla","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("tesla")"},"range":{"startRow":50,"startColumn":5,"endColumn":10,"endRow":50},"parent":421,"structure":[],"id":422},{"text":"InitializerClause","parent":420,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":423,"range":{"startRow":50,"startColumn":11,"endColumn":60,"endRow":50},"type":"other"},{"type":"other","text":"=","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"range":{"startRow":50,"startColumn":11,"endColumn":12,"endRow":50},"parent":423,"structure":[],"id":424},{"text":"FunctionCallExpr","parent":423,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":425,"range":{"startRow":50,"startColumn":13,"endColumn":60,"endRow":50},"type":"expr"},{"text":"DeclReferenceExpr","parent":425,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"ElectricCar","kind":"identifier("ElectricCar")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":426,"range":{"startRow":50,"startColumn":13,"endColumn":24,"endRow":50},"type":"expr"},{"type":"other","text":"ElectricCar","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("ElectricCar")"},"range":{"startRow":50,"startColumn":13,"endColumn":24,"endRow":50},"parent":426,"structure":[],"id":427},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"startRow":50,"startColumn":24,"endColumn":25,"endRow":50},"parent":425,"structure":[],"id":428},{"text":"LabeledExprList","parent":425,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":429,"range":{"startRow":50,"startColumn":25,"endColumn":59,"endRow":50},"type":"collection"},{"text":"LabeledExpr","parent":429,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"brand","kind":"identifier("brand")"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":430,"range":{"startRow":50,"startColumn":25,"endColumn":40,"endRow":50},"type":"other"},{"type":"other","text":"brand","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("brand")"},"range":{"startRow":50,"startColumn":25,"endColumn":30,"endRow":50},"parent":430,"structure":[],"id":431},{"type":"other","text":":","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"range":{"startRow":50,"startColumn":30,"endColumn":31,"endRow":50},"parent":430,"structure":[],"id":432},{"text":"StringLiteralExpr","parent":430,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":433,"range":{"startRow":50,"startColumn":32,"endColumn":39,"endRow":50},"type":"expr"},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":50,"startColumn":32,"endColumn":33,"endRow":50},"parent":433,"structure":[],"id":434},{"text":"StringLiteralSegmentList","parent":433,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"id":435,"range":{"startRow":50,"startColumn":33,"endColumn":38,"endRow":50},"type":"collection"},{"text":"StringSegment","parent":435,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Tesla","kind":"stringSegment("Tesla")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":436,"range":{"startRow":50,"startColumn":33,"endColumn":38,"endRow":50},"type":"other"},{"type":"other","text":"Tesla","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Tesla")"},"range":{"startRow":50,"startColumn":33,"endColumn":38,"endRow":50},"parent":436,"structure":[],"id":437},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":50,"startColumn":38,"endColumn":39,"endRow":50},"parent":433,"structure":[],"id":438},{"type":"other","text":",","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"},"range":{"startRow":50,"startColumn":39,"endColumn":40,"endRow":50},"parent":430,"structure":[],"id":439},{"text":"LabeledExpr","parent":429,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"batteryLevel","kind":"identifier("batteryLevel")"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"FloatLiteralExprSyntax"},"ref":"FloatLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":440,"range":{"startRow":50,"startColumn":41,"endColumn":59,"endRow":50},"type":"other"},{"type":"other","text":"batteryLevel","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("batteryLevel")"},"range":{"startRow":50,"startColumn":41,"endColumn":53,"endRow":50},"parent":440,"structure":[],"id":441},{"type":"other","text":":","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"range":{"startRow":50,"startColumn":53,"endColumn":54,"endRow":50},"parent":440,"structure":[],"id":442},{"text":"FloatLiteralExpr","parent":440,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"75.0","kind":"floatLiteral("75.0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":443,"range":{"startRow":50,"startColumn":55,"endColumn":59,"endRow":50},"type":"expr"},{"type":"other","text":"75.0","token":{"leadingTrivia":"","trailingTrivia":"","kind":"floatLiteral("75.0")"},"range":{"startRow":50,"startColumn":55,"endColumn":59,"endRow":50},"parent":443,"structure":[],"id":444},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"startRow":50,"startColumn":59,"endColumn":60,"endRow":50},"parent":425,"structure":[],"id":445},{"text":"MultipleTrailingClosureElementList","parent":425,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":446,"range":{"startRow":50,"startColumn":60,"endColumn":60,"endRow":50},"type":"collection"},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"VariableDeclSyntax"},"ref":"VariableDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":447,"range":{"startRow":51,"startColumn":1,"endColumn":34,"endRow":51},"type":"other"},{"text":"VariableDecl","parent":447,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":448,"range":{"startRow":51,"startColumn":1,"endColumn":34,"endRow":51},"type":"decl"},{"text":"AttributeList","parent":448,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":449,"range":{"startRow":50,"startColumn":60,"endColumn":60,"endRow":50},"type":"collection"},{"text":"DeclModifierList","parent":448,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":450,"range":{"startRow":50,"startColumn":60,"endColumn":60,"endRow":50},"type":"collection"},{"type":"other","text":"let","token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"range":{"startRow":51,"startColumn":1,"endColumn":4,"endRow":51},"parent":448,"structure":[],"id":451},{"text":"PatternBindingList","parent":448,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":452,"range":{"startRow":51,"startColumn":5,"endColumn":34,"endRow":51},"type":"collection"},{"text":"PatternBinding","parent":452,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":453,"range":{"startRow":51,"startColumn":5,"endColumn":34,"endRow":51},"type":"other"},{"text":"IdentifierPattern","parent":453,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"toyota","kind":"identifier("toyota")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"id":454,"range":{"startRow":51,"startColumn":5,"endColumn":11,"endRow":51},"type":"pattern"},{"type":"other","text":"toyota","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("toyota")"},"range":{"startRow":51,"startColumn":5,"endColumn":11,"endRow":51},"parent":454,"structure":[],"id":455},{"text":"InitializerClause","parent":453,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":456,"range":{"startRow":51,"startColumn":12,"endColumn":34,"endRow":51},"type":"other"},{"type":"other","text":"=","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"range":{"startRow":51,"startColumn":12,"endColumn":13,"endRow":51},"parent":456,"structure":[],"id":457},{"text":"FunctionCallExpr","parent":456,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":458,"range":{"startRow":51,"startColumn":14,"endColumn":34,"endRow":51},"type":"expr"},{"text":"DeclReferenceExpr","parent":458,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"Car","kind":"identifier("Car")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":459,"range":{"startRow":51,"startColumn":14,"endColumn":17,"endRow":51},"type":"expr"},{"type":"other","text":"Car","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("Car")"},"range":{"startRow":51,"startColumn":14,"endColumn":17,"endRow":51},"parent":459,"structure":[],"id":460},{"type":"other","text":"(","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"range":{"startRow":51,"startColumn":17,"endColumn":18,"endRow":51},"parent":458,"structure":[],"id":461},{"text":"LabeledExprList","parent":458,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":462,"range":{"startRow":51,"startColumn":18,"endColumn":33,"endRow":51},"type":"collection"},{"text":"LabeledExpr","parent":462,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"brand","kind":"identifier("brand")"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":463,"range":{"startRow":51,"startColumn":18,"endColumn":33,"endRow":51},"type":"other"},{"type":"other","text":"brand","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("brand")"},"range":{"startRow":51,"startColumn":18,"endColumn":23,"endRow":51},"parent":463,"structure":[],"id":464},{"type":"other","text":":","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"range":{"startRow":51,"startColumn":23,"endColumn":24,"endRow":51},"parent":463,"structure":[],"id":465},{"text":"StringLiteralExpr","parent":463,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":466,"range":{"startRow":51,"startColumn":25,"endColumn":33,"endRow":51},"type":"expr"},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":51,"startColumn":25,"endColumn":26,"endRow":51},"parent":466,"structure":[],"id":467},{"text":"StringLiteralSegmentList","parent":466,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"id":468,"range":{"startRow":51,"startColumn":26,"endColumn":32,"endRow":51},"type":"collection"},{"text":"StringSegment","parent":468,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Toyota","kind":"stringSegment("Toyota")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":469,"range":{"startRow":51,"startColumn":26,"endColumn":32,"endRow":51},"type":"other"},{"type":"other","text":"Toyota","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Toyota")"},"range":{"startRow":51,"startColumn":26,"endColumn":32,"endRow":51},"parent":469,"structure":[],"id":470},{"type":"other","text":""","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"range":{"startRow":51,"startColumn":32,"endColumn":33,"endRow":51},"parent":466,"structure":[],"id":471},{"type":"other","text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"startRow":51,"startColumn":33,"endColumn":34,"endRow":51},"parent":458,"structure":[],"id":472},{"text":"MultipleTrailingClosureElementList","parent":458,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":473,"range":{"startRow":51,"startColumn":34,"endColumn":34,"endRow":51},"type":"collection"},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionDeclSyntax"},"ref":"FunctionDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":474,"range":{"startRow":54,"startColumn":1,"endColumn":2,"endRow":59},"type":"other"},{"text":"FunctionDecl","parent":474,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"demonstrateVehicle","kind":"identifier("demonstrateVehicle")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"name":"signature","value":{"text":"FunctionSignatureSyntax"},"ref":"FunctionSignatureSyntax"},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":475,"range":{"startRow":54,"startColumn":1,"endColumn":2,"endRow":59},"type":"decl"},{"text":"AttributeList","parent":475,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":476,"range":{"endRow":51,"endColumn":34,"startRow":51,"startColumn":34},"type":"collection"},{"text":"DeclModifierList","parent":475,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":477,"range":{"endRow":51,"endColumn":34,"startRow":51,"startColumn":34},"type":"collection"},{"type":"other","text":"func","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>Demonstrate␣<\/span>protocol␣<\/span>usage<\/span>↲<\/span>"},"range":{"endRow":54,"endColumn":5,"startRow":54,"startColumn":1},"parent":475,"structure":[],"id":478},{"type":"other","text":"demonstrateVehicle","token":{"trailingTrivia":"","kind":"identifier("demonstrateVehicle")","leadingTrivia":""},"range":{"endRow":54,"endColumn":24,"startRow":54,"startColumn":6},"parent":475,"structure":[],"id":479},{"text":"FunctionSignature","parent":475,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeParameterClause"},{"value":{"text":"FunctionParameterClauseSyntax"},"ref":"FunctionParameterClauseSyntax","name":"parameterClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers"},{"value":{"text":"nil"},"name":"effectSpecifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenEffectSpecifiersAndReturnClause"},{"value":{"text":"nil"},"name":"returnClause"},{"value":{"text":"nil"},"name":"unexpectedAfterReturnClause"}],"id":480,"range":{"endRow":54,"endColumn":44,"startRow":54,"startColumn":24},"type":"other"},{"text":"FunctionParameterClause","parent":480,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndParameters"},{"value":{"text":"FunctionParameterListSyntax"},"ref":"FunctionParameterListSyntax","name":"parameters"},{"value":{"text":"nil"},"name":"unexpectedBetweenParametersAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":481,"range":{"endRow":54,"endColumn":44,"startRow":54,"startColumn":24},"type":"other"},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":54,"endColumn":25,"startRow":54,"startColumn":24},"parent":481,"structure":[],"id":482},{"text":"FunctionParameterList","parent":481,"structure":[{"value":{"text":"FunctionParameterSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":483,"range":{"endRow":54,"endColumn":43,"startRow":54,"startColumn":25},"type":"collection"},{"text":"FunctionParameter","parent":483,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndFirstName"},{"value":{"kind":"wildcard","text":"_"},"name":"firstName"},{"value":{"text":"nil"},"name":"unexpectedBetweenFirstNameAndSecondName"},{"value":{"kind":"identifier("vehicle")","text":"vehicle"},"name":"secondName"},{"value":{"text":"nil"},"name":"unexpectedBetweenSecondNameAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax","name":"type"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndEllipsis"},{"value":{"text":"nil"},"name":"ellipsis"},{"value":{"text":"nil"},"name":"unexpectedBetweenEllipsisAndDefaultValue"},{"value":{"text":"nil"},"name":"defaultValue"},{"value":{"text":"nil"},"name":"unexpectedBetweenDefaultValueAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":484,"range":{"endRow":54,"endColumn":43,"startRow":54,"startColumn":25},"type":"other"},{"text":"AttributeList","parent":484,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":485,"range":{"endRow":54,"endColumn":25,"startRow":54,"startColumn":25},"type":"collection"},{"text":"DeclModifierList","parent":484,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":486,"range":{"endRow":54,"endColumn":25,"startRow":54,"startColumn":25},"type":"collection"},{"type":"other","text":"_","token":{"trailingTrivia":"␣<\/span>","kind":"wildcard","leadingTrivia":""},"range":{"endRow":54,"endColumn":26,"startRow":54,"startColumn":25},"parent":484,"structure":[],"id":487},{"type":"other","text":"vehicle","token":{"trailingTrivia":"","kind":"identifier("vehicle")","leadingTrivia":""},"range":{"endRow":54,"endColumn":34,"startRow":54,"startColumn":27},"parent":484,"structure":[],"id":488},{"type":"other","text":":","token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""},"range":{"endRow":54,"endColumn":35,"startRow":54,"startColumn":34},"parent":484,"structure":[],"id":489},{"text":"IdentifierType","parent":484,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("Vehicle")","text":"Vehicle"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"id":490,"range":{"endRow":54,"endColumn":43,"startRow":54,"startColumn":36},"type":"type"},{"type":"other","text":"Vehicle","token":{"trailingTrivia":"","kind":"identifier("Vehicle")","leadingTrivia":""},"range":{"endRow":54,"endColumn":43,"startRow":54,"startColumn":36},"parent":490,"structure":[],"id":491},{"type":"other","text":")","token":{"trailingTrivia":"␣<\/span>","kind":"rightParen","leadingTrivia":""},"range":{"endRow":54,"endColumn":44,"startRow":54,"startColumn":43},"parent":481,"structure":[],"id":492},{"text":"CodeBlock","parent":475,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"id":493,"range":{"endRow":59,"endColumn":2,"startRow":54,"startColumn":45},"type":"other"},{"type":"other","text":"{","token":{"trailingTrivia":"","kind":"leftBrace","leadingTrivia":""},"range":{"endRow":54,"endColumn":46,"startRow":54,"startColumn":45},"parent":493,"structure":[],"id":494},{"text":"CodeBlockItemList","parent":493,"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"4"},"name":"Count"}],"id":495,"range":{"endRow":58,"endColumn":19,"startRow":55,"startColumn":5},"type":"collection"},{"text":"CodeBlockItem","parent":495,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":496,"range":{"endRow":55,"endColumn":45,"startRow":55,"startColumn":5},"type":"other"},{"text":"FunctionCallExpr","parent":496,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":497,"range":{"endRow":55,"endColumn":45,"startRow":55,"startColumn":5},"type":"expr"},{"text":"DeclReferenceExpr","parent":497,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":498,"range":{"endRow":55,"endColumn":10,"startRow":55,"startColumn":5},"type":"expr"},{"type":"other","text":"print","token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"endRow":55,"endColumn":10,"startRow":55,"startColumn":5},"parent":498,"structure":[],"id":499},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":55,"endColumn":11,"startRow":55,"startColumn":10},"parent":497,"structure":[],"id":500},{"text":"LabeledExprList","parent":497,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":501,"range":{"endRow":55,"endColumn":44,"startRow":55,"startColumn":11},"type":"collection"},{"text":"LabeledExpr","parent":501,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":502,"range":{"endRow":55,"endColumn":44,"startRow":55,"startColumn":11},"type":"other"},{"text":"StringLiteralExpr","parent":502,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"id":503,"range":{"endRow":55,"endColumn":44,"startRow":55,"startColumn":11},"type":"expr"},{"type":"other","text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"endRow":55,"endColumn":12,"startRow":55,"startColumn":11},"parent":503,"structure":[],"id":504},{"text":"StringLiteralSegmentList","parent":503,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"id":505,"range":{"endRow":55,"endColumn":43,"startRow":55,"startColumn":12},"type":"collection"},{"text":"StringSegment","parent":505,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Vehicle brand: ")","text":"Vehicle brand: "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":506,"range":{"endRow":55,"endColumn":27,"startRow":55,"startColumn":12},"type":"other"},{"type":"other","text":"Vehicle␣<\/span>brand:␣<\/span>","token":{"trailingTrivia":"","kind":"stringSegment("Vehicle brand: ")","leadingTrivia":""},"range":{"endRow":55,"endColumn":27,"startRow":55,"startColumn":12},"parent":506,"structure":[],"id":507},{"text":"ExpressionSegment","parent":505,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":508,"range":{"endRow":55,"endColumn":43,"startRow":55,"startColumn":27},"type":"other"},{"type":"other","text":"\\","token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"range":{"endRow":55,"endColumn":28,"startRow":55,"startColumn":27},"parent":508,"structure":[],"id":509},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":55,"endColumn":29,"startRow":55,"startColumn":28},"parent":508,"structure":[],"id":510},{"text":"LabeledExprList","parent":508,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":511,"range":{"endRow":55,"endColumn":42,"startRow":55,"startColumn":29},"type":"collection"},{"text":"LabeledExpr","parent":511,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":512,"range":{"endRow":55,"endColumn":42,"startRow":55,"startColumn":29},"type":"other"},{"text":"MemberAccessExpr","parent":512,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"id":513,"range":{"endRow":55,"endColumn":42,"startRow":55,"startColumn":29},"type":"expr"},{"text":"DeclReferenceExpr","parent":513,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("vehicle")","text":"vehicle"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":514,"range":{"endRow":55,"endColumn":36,"startRow":55,"startColumn":29},"type":"expr"},{"type":"other","text":"vehicle","token":{"trailingTrivia":"","kind":"identifier("vehicle")","leadingTrivia":""},"range":{"endRow":55,"endColumn":36,"startRow":55,"startColumn":29},"parent":514,"structure":[],"id":515},{"type":"other","text":".","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"range":{"endRow":55,"endColumn":37,"startRow":55,"startColumn":36},"parent":513,"structure":[],"id":516},{"text":"DeclReferenceExpr","parent":513,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("brand")","text":"brand"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":517,"range":{"endRow":55,"endColumn":42,"startRow":55,"startColumn":37},"type":"expr"},{"type":"other","text":"brand","token":{"trailingTrivia":"","kind":"identifier("brand")","leadingTrivia":""},"range":{"endRow":55,"endColumn":42,"startRow":55,"startColumn":37},"parent":517,"structure":[],"id":518},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endRow":55,"endColumn":43,"startRow":55,"startColumn":42},"parent":508,"structure":[],"id":519},{"text":"StringSegment","parent":505,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("")","text":""},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":520,"range":{"endRow":55,"endColumn":43,"startRow":55,"startColumn":43},"type":"other"},{"type":"other","text":"","token":{"trailingTrivia":"","kind":"stringSegment("")","leadingTrivia":""},"range":{"endRow":55,"endColumn":43,"startRow":55,"startColumn":43},"parent":520,"structure":[],"id":521},{"type":"other","text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"endRow":55,"endColumn":44,"startRow":55,"startColumn":43},"parent":503,"structure":[],"id":522},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endRow":55,"endColumn":45,"startRow":55,"startColumn":44},"parent":497,"structure":[],"id":523},{"text":"MultipleTrailingClosureElementList","parent":497,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":524,"range":{"endRow":55,"endColumn":45,"startRow":55,"startColumn":45},"type":"collection"},{"text":"CodeBlockItem","parent":495,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":525,"range":{"endRow":56,"endColumn":57,"startRow":56,"startColumn":5},"type":"other"},{"text":"FunctionCallExpr","parent":525,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":526,"range":{"endRow":56,"endColumn":57,"startRow":56,"startColumn":5},"type":"expr"},{"text":"DeclReferenceExpr","parent":526,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":527,"range":{"endRow":56,"endColumn":10,"startRow":56,"startColumn":5},"type":"expr"},{"type":"other","text":"print","token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"endRow":56,"endColumn":10,"startRow":56,"startColumn":5},"parent":527,"structure":[],"id":528},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":56,"endColumn":11,"startRow":56,"startColumn":10},"parent":526,"structure":[],"id":529},{"text":"LabeledExprList","parent":526,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":530,"range":{"endRow":56,"endColumn":56,"startRow":56,"startColumn":11},"type":"collection"},{"text":"LabeledExpr","parent":530,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":531,"range":{"endRow":56,"endColumn":56,"startRow":56,"startColumn":11},"type":"other"},{"text":"StringLiteralExpr","parent":531,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"id":532,"range":{"endRow":56,"endColumn":56,"startRow":56,"startColumn":11},"type":"expr"},{"type":"other","text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"endRow":56,"endColumn":12,"startRow":56,"startColumn":11},"parent":532,"structure":[],"id":533},{"text":"StringLiteralSegmentList","parent":532,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"id":534,"range":{"endRow":56,"endColumn":55,"startRow":56,"startColumn":12},"type":"collection"},{"text":"StringSegment","parent":534,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Number of wheels: ")","text":"Number of wheels: "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":535,"range":{"endRow":56,"endColumn":30,"startRow":56,"startColumn":12},"type":"other"},{"type":"other","text":"Number␣<\/span>of␣<\/span>wheels:␣<\/span>","token":{"trailingTrivia":"","kind":"stringSegment("Number of wheels: ")","leadingTrivia":""},"range":{"endRow":56,"endColumn":30,"startRow":56,"startColumn":12},"parent":535,"structure":[],"id":536},{"text":"ExpressionSegment","parent":534,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"kind":"backslash","text":"\\"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"id":537,"range":{"endRow":56,"endColumn":55,"startRow":56,"startColumn":30},"type":"other"},{"type":"other","text":"\\","token":{"trailingTrivia":"","kind":"backslash","leadingTrivia":""},"range":{"endRow":56,"endColumn":31,"startRow":56,"startColumn":30},"parent":537,"structure":[],"id":538},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":56,"endColumn":32,"startRow":56,"startColumn":31},"parent":537,"structure":[],"id":539},{"text":"LabeledExprList","parent":537,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"id":540,"range":{"endRow":56,"endColumn":54,"startRow":56,"startColumn":32},"type":"collection"},{"text":"LabeledExpr","parent":540,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":541,"range":{"endRow":56,"endColumn":54,"startRow":56,"startColumn":32},"type":"other"},{"text":"MemberAccessExpr","parent":541,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"id":542,"range":{"endRow":56,"endColumn":54,"startRow":56,"startColumn":32},"type":"expr"},{"text":"DeclReferenceExpr","parent":542,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("vehicle")","text":"vehicle"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":543,"range":{"endRow":56,"endColumn":39,"startRow":56,"startColumn":32},"type":"expr"},{"type":"other","text":"vehicle","token":{"trailingTrivia":"","kind":"identifier("vehicle")","leadingTrivia":""},"range":{"endRow":56,"endColumn":39,"startRow":56,"startColumn":32},"parent":543,"structure":[],"id":544},{"type":"other","text":".","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"range":{"endRow":56,"endColumn":40,"startRow":56,"startColumn":39},"parent":542,"structure":[],"id":545},{"text":"DeclReferenceExpr","parent":542,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("numberOfWheels")","text":"numberOfWheels"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":546,"range":{"endRow":56,"endColumn":54,"startRow":56,"startColumn":40},"type":"expr"},{"type":"other","text":"numberOfWheels","token":{"trailingTrivia":"","kind":"identifier("numberOfWheels")","leadingTrivia":""},"range":{"endRow":56,"endColumn":54,"startRow":56,"startColumn":40},"parent":546,"structure":[],"id":547},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endRow":56,"endColumn":55,"startRow":56,"startColumn":54},"parent":537,"structure":[],"id":548},{"text":"StringSegment","parent":534,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("")","text":""},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"id":549,"range":{"endRow":56,"endColumn":55,"startRow":56,"startColumn":55},"type":"other"},{"type":"other","text":"","token":{"trailingTrivia":"","kind":"stringSegment("")","leadingTrivia":""},"range":{"endRow":56,"endColumn":55,"startRow":56,"startColumn":55},"parent":549,"structure":[],"id":550},{"type":"other","text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"endRow":56,"endColumn":56,"startRow":56,"startColumn":55},"parent":532,"structure":[],"id":551},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endRow":56,"endColumn":57,"startRow":56,"startColumn":56},"parent":526,"structure":[],"id":552},{"text":"MultipleTrailingClosureElementList","parent":526,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":553,"range":{"endRow":56,"endColumn":57,"startRow":56,"startColumn":57},"type":"collection"},{"text":"CodeBlockItem","parent":495,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":554,"range":{"endRow":57,"endColumn":20,"startRow":57,"startColumn":5},"type":"other"},{"text":"FunctionCallExpr","parent":554,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":555,"range":{"endRow":57,"endColumn":20,"startRow":57,"startColumn":5},"type":"expr"},{"text":"MemberAccessExpr","parent":555,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"id":556,"range":{"endRow":57,"endColumn":18,"startRow":57,"startColumn":5},"type":"expr"},{"text":"DeclReferenceExpr","parent":556,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("vehicle")","text":"vehicle"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":557,"range":{"endRow":57,"endColumn":12,"startRow":57,"startColumn":5},"type":"expr"},{"type":"other","text":"vehicle","token":{"trailingTrivia":"","kind":"identifier("vehicle")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"endRow":57,"endColumn":12,"startRow":57,"startColumn":5},"parent":557,"structure":[],"id":558},{"type":"other","text":".","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"range":{"endRow":57,"endColumn":13,"startRow":57,"startColumn":12},"parent":556,"structure":[],"id":559},{"text":"DeclReferenceExpr","parent":556,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("start")","text":"start"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":560,"range":{"endRow":57,"endColumn":18,"startRow":57,"startColumn":13},"type":"expr"},{"type":"other","text":"start","token":{"trailingTrivia":"","kind":"identifier("start")","leadingTrivia":""},"range":{"endRow":57,"endColumn":18,"startRow":57,"startColumn":13},"parent":560,"structure":[],"id":561},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":57,"endColumn":19,"startRow":57,"startColumn":18},"parent":555,"structure":[],"id":562},{"text":"LabeledExprList","parent":555,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":563,"range":{"endRow":57,"endColumn":19,"startRow":57,"startColumn":19},"type":"collection"},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endRow":57,"endColumn":20,"startRow":57,"startColumn":19},"parent":555,"structure":[],"id":564},{"text":"MultipleTrailingClosureElementList","parent":555,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":565,"range":{"endRow":57,"endColumn":20,"startRow":57,"startColumn":20},"type":"collection"},{"text":"CodeBlockItem","parent":495,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":566,"range":{"endRow":58,"endColumn":19,"startRow":58,"startColumn":5},"type":"other"},{"text":"FunctionCallExpr","parent":566,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"id":567,"range":{"endRow":58,"endColumn":19,"startRow":58,"startColumn":5},"type":"expr"},{"text":"MemberAccessExpr","parent":567,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"id":568,"range":{"endRow":58,"endColumn":17,"startRow":58,"startColumn":5},"type":"expr"},{"text":"DeclReferenceExpr","parent":568,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("vehicle")","text":"vehicle"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":569,"range":{"endRow":58,"endColumn":12,"startRow":58,"startColumn":5},"type":"expr"},{"type":"other","text":"vehicle","token":{"trailingTrivia":"","kind":"identifier("vehicle")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"endRow":58,"endColumn":12,"startRow":58,"startColumn":5},"parent":569,"structure":[],"id":570},{"type":"other","text":".","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"range":{"endRow":58,"endColumn":13,"startRow":58,"startColumn":12},"parent":568,"structure":[],"id":571},{"text":"DeclReferenceExpr","parent":568,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("stop")","text":"stop"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"id":572,"range":{"endRow":58,"endColumn":17,"startRow":58,"startColumn":13},"type":"expr"},{"type":"other","text":"stop","token":{"trailingTrivia":"","kind":"identifier("stop")","leadingTrivia":""},"range":{"endRow":58,"endColumn":17,"startRow":58,"startColumn":13},"parent":572,"structure":[],"id":573},{"type":"other","text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endRow":58,"endColumn":18,"startRow":58,"startColumn":17},"parent":567,"structure":[],"id":574},{"text":"LabeledExprList","parent":567,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":575,"range":{"endRow":58,"endColumn":18,"startRow":58,"startColumn":18},"type":"collection"},{"type":"other","text":")","token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"endRow":58,"endColumn":19,"startRow":58,"startColumn":18},"parent":567,"structure":[],"id":576},{"text":"MultipleTrailingClosureElementList","parent":567,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"id":577,"range":{"endRow":58,"endColumn":19,"startRow":58,"startColumn":19},"type":"collection"},{"type":"other","text":"}","token":{"trailingTrivia":"","kind":"rightBrace","leadingTrivia":"↲<\/span>"},"range":{"endRow":59,"endColumn":2,"startRow":59,"startColumn":1},"parent":493,"structure":[],"id":578},{"text":"CodeBlockItem","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionDeclSyntax"},"ref":"FunctionDeclSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":579,"range":{"endRow":66,"endColumn":2,"startRow":62,"startColumn":1},"type":"other"},{"text":"FunctionDecl","parent":579,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndFuncKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.func)","text":"func"},"name":"funcKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenFuncKeywordAndName"},{"value":{"kind":"identifier("demonstrateElectricVehicle")","text":"demonstrateElectricVehicle"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericParameterClause"},{"value":{"text":"nil"},"name":"genericParameterClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenGenericParameterClauseAndSignature"},{"value":{"text":"FunctionSignatureSyntax"},"ref":"FunctionSignatureSyntax","name":"signature"},{"value":{"text":"nil"},"name":"unexpectedBetweenSignatureAndGenericWhereClause"},{"value":{"text":"nil"},"name":"genericWhereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenGenericWhereClauseAndBody"},{"value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax","name":"body"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}],"id":580,"range":{"endRow":66,"endColumn":2,"startRow":62,"startColumn":1},"type":"decl"},{"text":"AttributeList","parent":580,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":581,"range":{"endColumn":2,"startColumn":2,"endRow":59,"startRow":59},"type":"collection"},{"text":"DeclModifierList","parent":580,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":582,"range":{"endColumn":2,"startColumn":2,"endRow":59,"startRow":59},"type":"collection"},{"type":"other","text":"func","token":{"kind":"keyword(SwiftSyntax.Keyword.func)","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>Demonstrate␣<\/span>protocol␣<\/span>composition<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"range":{"endColumn":5,"startColumn":1,"endRow":62,"startRow":62},"parent":580,"structure":[],"id":583},{"type":"other","text":"demonstrateElectricVehicle","token":{"kind":"identifier("demonstrateElectricVehicle")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":32,"startColumn":6,"endRow":62,"startRow":62},"parent":580,"structure":[],"id":584},{"text":"FunctionSignature","parent":580,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"ref":"FunctionParameterClauseSyntax","name":"parameterClause","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"id":585,"range":{"endColumn":63,"startColumn":32,"endRow":62,"startRow":62},"type":"other"},{"text":"FunctionParameterClause","parent":585,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"ref":"FunctionParameterListSyntax","name":"parameters","value":{"text":"FunctionParameterListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":586,"range":{"endColumn":63,"startColumn":32,"endRow":62,"startRow":62},"type":"other"},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":33,"startColumn":32,"endRow":62,"startRow":62},"parent":586,"structure":[],"id":587},{"text":"FunctionParameterList","parent":586,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":588,"range":{"endColumn":62,"startColumn":33,"endRow":62,"startRow":62},"type":"collection"},{"text":"FunctionParameter","parent":588,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFirstName","value":{"text":"nil"}},{"name":"firstName","value":{"text":"_","kind":"wildcard"}},{"name":"unexpectedBetweenFirstNameAndSecondName","value":{"text":"nil"}},{"name":"secondName","value":{"text":"vehicle","kind":"identifier("vehicle")"}},{"name":"unexpectedBetweenSecondNameAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"ref":"CompositionTypeSyntax","name":"type","value":{"text":"CompositionTypeSyntax"}},{"name":"unexpectedBetweenTypeAndEllipsis","value":{"text":"nil"}},{"name":"ellipsis","value":{"text":"nil"}},{"name":"unexpectedBetweenEllipsisAndDefaultValue","value":{"text":"nil"}},{"name":"defaultValue","value":{"text":"nil"}},{"name":"unexpectedBetweenDefaultValueAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":589,"range":{"endColumn":62,"startColumn":33,"endRow":62,"startRow":62},"type":"other"},{"text":"AttributeList","parent":589,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"id":590,"range":{"endColumn":33,"startColumn":33,"endRow":62,"startRow":62},"type":"collection"},{"text":"DeclModifierList","parent":589,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":591,"range":{"endColumn":33,"startColumn":33,"endRow":62,"startRow":62},"type":"collection"},{"type":"other","text":"_","token":{"kind":"wildcard","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":34,"startColumn":33,"endRow":62,"startRow":62},"parent":589,"structure":[],"id":592},{"type":"other","text":"vehicle","token":{"kind":"identifier("vehicle")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":42,"startColumn":35,"endRow":62,"startRow":62},"parent":589,"structure":[],"id":593},{"type":"other","text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":43,"startColumn":42,"endRow":62,"startRow":62},"parent":589,"structure":[],"id":594},{"text":"CompositionType","parent":589,"structure":[{"name":"unexpectedBeforeElements","value":{"text":"nil"}},{"ref":"CompositionTypeElementListSyntax","name":"elements","value":{"text":"CompositionTypeElementListSyntax"}},{"name":"unexpectedAfterElements","value":{"text":"nil"}}],"id":595,"range":{"endColumn":62,"startColumn":44,"endRow":62,"startRow":62},"type":"type"},{"text":"CompositionTypeElementList","parent":595,"structure":[{"name":"Element","value":{"text":"CompositionTypeElementSyntax"}},{"name":"Count","value":{"text":"2"}}],"id":596,"range":{"endColumn":62,"startColumn":44,"endRow":62,"startRow":62},"type":"collection"},{"text":"CompositionTypeElement","parent":596,"structure":[{"name":"unexpectedBeforeType","value":{"text":"nil"}},{"ref":"IdentifierTypeSyntax","name":"type","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenTypeAndAmpersand","value":{"text":"nil"}},{"name":"ampersand","value":{"text":"&","kind":"binaryOperator("&")"}},{"name":"unexpectedAfterAmpersand","value":{"text":"nil"}}],"id":597,"range":{"endColumn":53,"startColumn":44,"endRow":62,"startRow":62},"type":"other"},{"text":"IdentifierType","parent":597,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Vehicle","kind":"identifier("Vehicle")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":598,"range":{"endColumn":51,"startColumn":44,"endRow":62,"startRow":62},"type":"type"},{"type":"other","text":"Vehicle","token":{"kind":"identifier("Vehicle")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":51,"startColumn":44,"endRow":62,"startRow":62},"parent":598,"structure":[],"id":599},{"type":"other","text":"&","token":{"kind":"binaryOperator("&")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":53,"startColumn":52,"endRow":62,"startRow":62},"parent":597,"structure":[],"id":600},{"text":"CompositionTypeElement","parent":596,"structure":[{"name":"unexpectedBeforeType","value":{"text":"nil"}},{"ref":"IdentifierTypeSyntax","name":"type","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenTypeAndAmpersand","value":{"text":"nil"}},{"name":"ampersand","value":{"text":"nil"}},{"name":"unexpectedAfterAmpersand","value":{"text":"nil"}}],"id":601,"range":{"endColumn":62,"startColumn":54,"endRow":62,"startRow":62},"type":"other"},{"text":"IdentifierType","parent":601,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Electric","kind":"identifier("Electric")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"id":602,"range":{"endColumn":62,"startColumn":54,"endRow":62,"startRow":62},"type":"type"},{"type":"other","text":"Electric","token":{"kind":"identifier("Electric")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":62,"startColumn":54,"endRow":62,"startRow":62},"parent":602,"structure":[],"id":603},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":63,"startColumn":62,"endRow":62,"startRow":62},"parent":586,"structure":[],"id":604},{"text":"CodeBlock","parent":580,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":605,"range":{"endColumn":2,"startColumn":64,"endRow":66,"startRow":62},"type":"other"},{"type":"other","text":"{","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":65,"startColumn":64,"endRow":62,"startRow":62},"parent":605,"structure":[],"id":606},{"text":"CodeBlockItemList","parent":605,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"3"}}],"id":607,"range":{"endColumn":21,"startColumn":5,"endRow":65,"startRow":63},"type":"collection"},{"text":"CodeBlockItem","parent":607,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":608,"range":{"endColumn":32,"startColumn":5,"endRow":63,"startRow":63},"type":"other"},{"text":"FunctionCallExpr","parent":608,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":609,"range":{"endColumn":32,"startColumn":5,"endRow":63,"startRow":63},"type":"expr"},{"text":"DeclReferenceExpr","parent":609,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"demonstrateVehicle","kind":"identifier("demonstrateVehicle")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":610,"range":{"endColumn":23,"startColumn":5,"endRow":63,"startRow":63},"type":"expr"},{"type":"other","text":"demonstrateVehicle","token":{"kind":"identifier("demonstrateVehicle")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"range":{"endColumn":23,"startColumn":5,"endRow":63,"startRow":63},"parent":610,"structure":[],"id":611},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":24,"startColumn":23,"endRow":63,"startRow":63},"parent":609,"structure":[],"id":612},{"text":"LabeledExprList","parent":609,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":613,"range":{"endColumn":31,"startColumn":24,"endRow":63,"startRow":63},"type":"collection"},{"text":"LabeledExpr","parent":613,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":614,"range":{"endColumn":31,"startColumn":24,"endRow":63,"startRow":63},"type":"other"},{"text":"DeclReferenceExpr","parent":614,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"vehicle","kind":"identifier("vehicle")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":615,"range":{"endColumn":31,"startColumn":24,"endRow":63,"startRow":63},"type":"expr"},{"type":"other","text":"vehicle","token":{"kind":"identifier("vehicle")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":31,"startColumn":24,"endRow":63,"startRow":63},"parent":615,"structure":[],"id":616},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":32,"startColumn":31,"endRow":63,"startRow":63},"parent":609,"structure":[],"id":617},{"text":"MultipleTrailingClosureElementList","parent":609,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":618,"range":{"endColumn":32,"startColumn":32,"endRow":63,"startRow":63},"type":"collection"},{"text":"CodeBlockItem","parent":607,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":619,"range":{"endColumn":53,"startColumn":5,"endRow":64,"startRow":64},"type":"other"},{"text":"FunctionCallExpr","parent":619,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":620,"range":{"endColumn":53,"startColumn":5,"endRow":64,"startRow":64},"type":"expr"},{"text":"DeclReferenceExpr","parent":620,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":621,"range":{"endColumn":10,"startColumn":5,"endRow":64,"startRow":64},"type":"expr"},{"type":"other","text":"print","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"range":{"endColumn":10,"startColumn":5,"endRow":64,"startRow":64},"parent":621,"structure":[],"id":622},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":11,"startColumn":10,"endRow":64,"startRow":64},"parent":620,"structure":[],"id":623},{"text":"LabeledExprList","parent":620,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":624,"range":{"endColumn":52,"startColumn":11,"endRow":64,"startRow":64},"type":"collection"},{"text":"LabeledExpr","parent":624,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":625,"range":{"endColumn":52,"startColumn":11,"endRow":64,"startRow":64},"type":"other"},{"text":"StringLiteralExpr","parent":625,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":626,"range":{"endColumn":52,"startColumn":11,"endRow":64,"startRow":64},"type":"expr"},{"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":12,"startColumn":11,"endRow":64,"startRow":64},"parent":626,"structure":[],"id":627},{"text":"StringLiteralSegmentList","parent":626,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"id":628,"range":{"endColumn":51,"startColumn":12,"endRow":64,"startRow":64},"type":"collection"},{"text":"StringSegment","parent":628,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Battery level: ","kind":"stringSegment("Battery level: ")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":629,"range":{"endColumn":27,"startColumn":12,"endRow":64,"startRow":64},"type":"other"},{"type":"other","text":"Battery␣<\/span>level:␣<\/span>","token":{"kind":"stringSegment("Battery level: ")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":27,"startColumn":12,"endRow":64,"startRow":64},"parent":629,"structure":[],"id":630},{"text":"ExpressionSegment","parent":628,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"expressions","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"id":631,"range":{"endColumn":50,"startColumn":27,"endRow":64,"startRow":64},"type":"other"},{"type":"other","text":"\\","token":{"kind":"backslash","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":28,"startColumn":27,"endRow":64,"startRow":64},"parent":631,"structure":[],"id":632},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":29,"startColumn":28,"endRow":64,"startRow":64},"parent":631,"structure":[],"id":633},{"text":"LabeledExprList","parent":631,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":634,"range":{"endColumn":49,"startColumn":29,"endRow":64,"startRow":64},"type":"collection"},{"text":"LabeledExpr","parent":634,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"MemberAccessExprSyntax","name":"expression","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":635,"range":{"endColumn":49,"startColumn":29,"endRow":64,"startRow":64},"type":"other"},{"text":"MemberAccessExpr","parent":635,"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"base","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"id":636,"range":{"endColumn":49,"startColumn":29,"endRow":64,"startRow":64},"type":"expr"},{"text":"DeclReferenceExpr","parent":636,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"vehicle","kind":"identifier("vehicle")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":637,"range":{"endColumn":36,"startColumn":29,"endRow":64,"startRow":64},"type":"expr"},{"type":"other","text":"vehicle","token":{"kind":"identifier("vehicle")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":36,"startColumn":29,"endRow":64,"startRow":64},"parent":637,"structure":[],"id":638},{"type":"other","text":".","token":{"kind":"period","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":37,"startColumn":36,"endRow":64,"startRow":64},"parent":636,"structure":[],"id":639},{"text":"DeclReferenceExpr","parent":636,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"batteryLevel","kind":"identifier("batteryLevel")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":640,"range":{"endColumn":49,"startColumn":37,"endRow":64,"startRow":64},"type":"expr"},{"type":"other","text":"batteryLevel","token":{"kind":"identifier("batteryLevel")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":49,"startColumn":37,"endRow":64,"startRow":64},"parent":640,"structure":[],"id":641},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":50,"startColumn":49,"endRow":64,"startRow":64},"parent":631,"structure":[],"id":642},{"text":"StringSegment","parent":628,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"%","kind":"stringSegment("%")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":643,"range":{"endColumn":51,"startColumn":50,"endRow":64,"startRow":64},"type":"other"},{"type":"other","text":"%","token":{"kind":"stringSegment("%")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":51,"startColumn":50,"endRow":64,"startRow":64},"parent":643,"structure":[],"id":644},{"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":52,"startColumn":51,"endRow":64,"startRow":64},"parent":626,"structure":[],"id":645},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":53,"startColumn":52,"endRow":64,"startRow":64},"parent":620,"structure":[],"id":646},{"text":"MultipleTrailingClosureElementList","parent":620,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":647,"range":{"endColumn":53,"startColumn":53,"endRow":64,"startRow":64},"type":"collection"},{"text":"CodeBlockItem","parent":607,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":648,"range":{"endColumn":21,"startColumn":5,"endRow":65,"startRow":65},"type":"other"},{"text":"FunctionCallExpr","parent":648,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"MemberAccessExprSyntax","name":"calledExpression","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":649,"range":{"endColumn":21,"startColumn":5,"endRow":65,"startRow":65},"type":"expr"},{"text":"MemberAccessExpr","parent":649,"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"base","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"id":650,"range":{"endColumn":19,"startColumn":5,"endRow":65,"startRow":65},"type":"expr"},{"text":"DeclReferenceExpr","parent":650,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"vehicle","kind":"identifier("vehicle")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":651,"range":{"endColumn":12,"startColumn":5,"endRow":65,"startRow":65},"type":"expr"},{"type":"other","text":"vehicle","token":{"kind":"identifier("vehicle")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"range":{"endColumn":12,"startColumn":5,"endRow":65,"startRow":65},"parent":651,"structure":[],"id":652},{"type":"other","text":".","token":{"kind":"period","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":13,"startColumn":12,"endRow":65,"startRow":65},"parent":650,"structure":[],"id":653},{"text":"DeclReferenceExpr","parent":650,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"charge","kind":"identifier("charge")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":654,"range":{"endColumn":19,"startColumn":13,"endRow":65,"startRow":65},"type":"expr"},{"type":"other","text":"charge","token":{"kind":"identifier("charge")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":19,"startColumn":13,"endRow":65,"startRow":65},"parent":654,"structure":[],"id":655},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":20,"startColumn":19,"endRow":65,"startRow":65},"parent":649,"structure":[],"id":656},{"text":"LabeledExprList","parent":649,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":657,"range":{"endColumn":20,"startColumn":20,"endRow":65,"startRow":65},"type":"collection"},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":21,"startColumn":20,"endRow":65,"startRow":65},"parent":649,"structure":[],"id":658},{"text":"MultipleTrailingClosureElementList","parent":649,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":659,"range":{"endColumn":21,"startColumn":21,"endRow":65,"startRow":65},"type":"collection"},{"type":"other","text":"}","token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"endColumn":2,"startColumn":1,"endRow":66,"startRow":66},"parent":605,"structure":[],"id":660},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":661,"range":{"endColumn":30,"startColumn":1,"endRow":69,"startRow":69},"type":"other"},{"text":"FunctionCallExpr","parent":661,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":662,"range":{"endColumn":30,"startColumn":1,"endRow":69,"startRow":69},"type":"expr"},{"text":"DeclReferenceExpr","parent":662,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":663,"range":{"endColumn":6,"startColumn":1,"endRow":69,"startRow":69},"type":"expr"},{"type":"other","text":"print","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>↲<\/span>\/\/␣<\/span>Test␣<\/span>the␣<\/span>implementations<\/span>↲<\/span>","trailingTrivia":""},"range":{"endColumn":6,"startColumn":1,"endRow":69,"startRow":69},"parent":663,"structure":[],"id":664},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":7,"startColumn":6,"endRow":69,"startRow":69},"parent":662,"structure":[],"id":665},{"text":"LabeledExprList","parent":662,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":666,"range":{"endColumn":29,"startColumn":7,"endRow":69,"startRow":69},"type":"collection"},{"text":"LabeledExpr","parent":666,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":667,"range":{"endColumn":29,"startColumn":7,"endRow":69,"startRow":69},"type":"other"},{"text":"StringLiteralExpr","parent":667,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":668,"range":{"endColumn":29,"startColumn":7,"endRow":69,"startRow":69},"type":"expr"},{"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":8,"startColumn":7,"endRow":69,"startRow":69},"parent":668,"structure":[],"id":669},{"text":"StringLiteralSegmentList","parent":668,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"id":670,"range":{"endColumn":28,"startColumn":8,"endRow":69,"startRow":69},"type":"collection"},{"text":"StringSegment","parent":670,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Testing regular car:","kind":"stringSegment("Testing regular car:")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":671,"range":{"endColumn":28,"startColumn":8,"endRow":69,"startRow":69},"type":"other"},{"type":"other","text":"Testing␣<\/span>regular␣<\/span>car:","token":{"kind":"stringSegment("Testing regular car:")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":28,"startColumn":8,"endRow":69,"startRow":69},"parent":671,"structure":[],"id":672},{"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":29,"startColumn":28,"endRow":69,"startRow":69},"parent":668,"structure":[],"id":673},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":30,"startColumn":29,"endRow":69,"startRow":69},"parent":662,"structure":[],"id":674},{"text":"MultipleTrailingClosureElementList","parent":662,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":675,"range":{"endColumn":30,"startColumn":30,"endRow":69,"startRow":69},"type":"collection"},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":676,"range":{"endColumn":27,"startColumn":1,"endRow":70,"startRow":70},"type":"other"},{"text":"FunctionCallExpr","parent":676,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":677,"range":{"endColumn":27,"startColumn":1,"endRow":70,"startRow":70},"type":"expr"},{"text":"DeclReferenceExpr","parent":677,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"demonstrateVehicle","kind":"identifier("demonstrateVehicle")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":678,"range":{"endColumn":19,"startColumn":1,"endRow":70,"startRow":70},"type":"expr"},{"type":"other","text":"demonstrateVehicle","token":{"kind":"identifier("demonstrateVehicle")","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"endColumn":19,"startColumn":1,"endRow":70,"startRow":70},"parent":678,"structure":[],"id":679},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":20,"startColumn":19,"endRow":70,"startRow":70},"parent":677,"structure":[],"id":680},{"text":"LabeledExprList","parent":677,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":681,"range":{"endColumn":26,"startColumn":20,"endRow":70,"startRow":70},"type":"collection"},{"text":"LabeledExpr","parent":681,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":682,"range":{"endColumn":26,"startColumn":20,"endRow":70,"startRow":70},"type":"other"},{"text":"DeclReferenceExpr","parent":682,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"toyota","kind":"identifier("toyota")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":683,"range":{"endColumn":26,"startColumn":20,"endRow":70,"startRow":70},"type":"expr"},{"type":"other","text":"toyota","token":{"kind":"identifier("toyota")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":26,"startColumn":20,"endRow":70,"startRow":70},"parent":683,"structure":[],"id":684},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":27,"startColumn":26,"endRow":70,"startRow":70},"parent":677,"structure":[],"id":685},{"text":"MultipleTrailingClosureElementList","parent":677,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":686,"range":{"endColumn":27,"startColumn":27,"endRow":70,"startRow":70},"type":"collection"},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":687,"range":{"endColumn":33,"startColumn":1,"endRow":72,"startRow":72},"type":"other"},{"text":"FunctionCallExpr","parent":687,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":688,"range":{"endColumn":33,"startColumn":1,"endRow":72,"startRow":72},"type":"expr"},{"text":"DeclReferenceExpr","parent":688,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":689,"range":{"endColumn":6,"startColumn":1,"endRow":72,"startRow":72},"type":"expr"},{"type":"other","text":"print","token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>↲<\/span>","trailingTrivia":""},"range":{"endColumn":6,"startColumn":1,"endRow":72,"startRow":72},"parent":689,"structure":[],"id":690},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":7,"startColumn":6,"endRow":72,"startRow":72},"parent":688,"structure":[],"id":691},{"text":"LabeledExprList","parent":688,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":692,"range":{"endColumn":32,"startColumn":7,"endRow":72,"startRow":72},"type":"collection"},{"text":"LabeledExpr","parent":692,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":693,"range":{"endColumn":32,"startColumn":7,"endRow":72,"startRow":72},"type":"other"},{"text":"StringLiteralExpr","parent":693,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":694,"range":{"endColumn":32,"startColumn":7,"endRow":72,"startRow":72},"type":"expr"},{"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":8,"startColumn":7,"endRow":72,"startRow":72},"parent":694,"structure":[],"id":695},{"text":"StringLiteralSegmentList","parent":694,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"2"}}],"id":696,"range":{"endColumn":31,"startColumn":8,"endRow":72,"startRow":72},"type":"collection"},{"text":"StringSegment","parent":696,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"\\n","kind":"stringSegment("\\\\n")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":697,"range":{"endColumn":10,"startColumn":8,"endRow":72,"startRow":72},"type":"other"},{"type":"other","text":"\\n","token":{"kind":"stringSegment("\\\\n")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":10,"startColumn":8,"endRow":72,"startRow":72},"parent":697,"structure":[],"id":698},{"text":"StringSegment","parent":696,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Testing electric car:","kind":"stringSegment("Testing electric car:")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"id":699,"range":{"endColumn":31,"startColumn":10,"endRow":72,"startRow":72},"type":"other"},{"type":"other","text":"Testing␣<\/span>electric␣<\/span>car:","token":{"kind":"stringSegment("Testing electric car:")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":31,"startColumn":10,"endRow":72,"startRow":72},"parent":699,"structure":[],"id":700},{"type":"other","text":""","token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":32,"startColumn":31,"endRow":72,"startRow":72},"parent":694,"structure":[],"id":701},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":33,"startColumn":32,"endRow":72,"startRow":72},"parent":688,"structure":[],"id":702},{"text":"MultipleTrailingClosureElementList","parent":688,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":703,"range":{"endColumn":33,"startColumn":33,"endRow":72,"startRow":72},"type":"collection"},{"text":"CodeBlockItem","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":704,"range":{"endColumn":34,"startColumn":1,"endRow":73,"startRow":73},"type":"other"},{"text":"FunctionCallExpr","parent":704,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"id":705,"range":{"endColumn":34,"startColumn":1,"endRow":73,"startRow":73},"type":"expr"},{"text":"DeclReferenceExpr","parent":705,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"demonstrateElectricVehicle","kind":"identifier("demonstrateElectricVehicle")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":706,"range":{"endColumn":27,"startColumn":1,"endRow":73,"startRow":73},"type":"expr"},{"type":"other","text":"demonstrateElectricVehicle","token":{"kind":"identifier("demonstrateElectricVehicle")","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"endColumn":27,"startColumn":1,"endRow":73,"startRow":73},"parent":706,"structure":[],"id":707},{"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":28,"startColumn":27,"endRow":73,"startRow":73},"parent":705,"structure":[],"id":708},{"text":"LabeledExprList","parent":705,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":709,"range":{"endColumn":33,"startColumn":28,"endRow":73,"startRow":73},"type":"collection"},{"text":"LabeledExpr","parent":709,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":710,"range":{"endColumn":33,"startColumn":28,"endRow":73,"startRow":73},"type":"other"},{"text":"DeclReferenceExpr","parent":710,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"tesla","kind":"identifier("tesla")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":711,"range":{"endColumn":33,"startColumn":28,"endRow":73,"startRow":73},"type":"expr"},{"type":"other","text":"tesla","token":{"kind":"identifier("tesla")","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":33,"startColumn":28,"endRow":73,"startRow":73},"parent":711,"structure":[],"id":712},{"type":"other","text":")","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"endColumn":34,"startColumn":33,"endRow":73,"startRow":73},"parent":705,"structure":[],"id":713},{"text":"MultipleTrailingClosureElementList","parent":705,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":714,"range":{"endColumn":34,"startColumn":34,"endRow":73,"startRow":73},"type":"collection"},{"type":"other","text":"","token":{"kind":"endOfFile","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"endColumn":1,"startColumn":1,"endRow":74,"startRow":74},"parent":0,"structure":[],"id":715}] diff --git a/Package.swift b/Package.swift index 42c9345..6a95649 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,7 @@ import PackageDescription +// swiftlint:disable:next explicit_top_level_acl explicit_acl let package = Package( name: "SyntaxKit", platforms: [ diff --git a/Sources/SyntaxKit/Array+LiteralValue.swift b/Sources/SyntaxKit/Array+LiteralValue.swift new file mode 100644 index 0000000..baf3c7b --- /dev/null +++ b/Sources/SyntaxKit/Array+LiteralValue.swift @@ -0,0 +1,51 @@ +// +// Array+LiteralValue.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +extension Array: LiteralValue where Element == String { + /// The Swift type name for an array of strings. + public var typeName: String { "[String]" } + + /// Renders this array as a Swift literal string with proper escaping. + public var literalString: String { + let elements = self.map { element in + // Escape quotes and newlines + let escaped = + element + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + .replacingOccurrences(of: "\n", with: "\\n") + .replacingOccurrences(of: "\r", with: "\\r") + .replacingOccurrences(of: "\t", with: "\\t") + return "\"\(escaped)\"" + }.joined(separator: ", ") + return "[\(elements)]" + } +} diff --git a/Sources/SyntaxKit/ArrayLiteral.swift b/Sources/SyntaxKit/ArrayLiteral.swift new file mode 100644 index 0000000..e752bc1 --- /dev/null +++ b/Sources/SyntaxKit/ArrayLiteral.swift @@ -0,0 +1,74 @@ +// +// ArrayLiteral.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// An array value that can be used as a literal. +public struct ArrayLiteral: LiteralValue { + let elements: [Literal] + + /// Creates an array with the given elements. + /// - Parameter elements: The array elements. + public init(_ elements: [Literal]) { + self.elements = elements + } + + /// The Swift type name for this array. + public var typeName: String { + if elements.isEmpty { + return "[Any]" + } + let elementType = elements.first?.typeName ?? "Any" + return "[\(elementType)]" + } + + /// Renders this array as a Swift literal string. + public var literalString: String { + let elementStrings = elements.map { element in + switch element { + case .integer(let value): return String(value) + case .float(let value): return String(value) + case .string(let value): return "\"\(value)\"" + case .boolean(let value): return value ? "true" : "false" + case .nil: return "nil" + case .ref(let value): return value + case .tuple(let tupleElements): + let tuple = TupleLiteral(tupleElements) + return tuple.literalString + case .array(let arrayElements): + let array = ArrayLiteral(arrayElements) + return array.literalString + case .dictionary(let dictionaryElements): + let dictionary = DictionaryLiteral(dictionaryElements) + return dictionary.literalString + } + } + return "[\(elementStrings.joined(separator: ", "))]" + } +} diff --git a/Sources/SyntaxKit/Assignment.swift b/Sources/SyntaxKit/Assignment.swift index 4a0af2e..a6502da 100644 --- a/Sources/SyntaxKit/Assignment.swift +++ b/Sources/SyntaxKit/Assignment.swift @@ -32,40 +32,51 @@ import SwiftSyntax /// An assignment expression. public struct Assignment: CodeBlock { private let target: String - private let value: String + private let valueExpr: ExprSyntax - /// Creates an assignment expression. - /// - Parameters: - /// - target: The variable to assign to. - /// - value: The value to assign. - public init(_ target: String, _ value: String) { + /// Creates an assignment where the value is a literal. + public init(_ target: String, _ literal: Literal) { self.target = target - self.value = value + guard let expr = literal.syntax.as(ExprSyntax.self) else { + fatalError("Literal.syntax did not produce ExprSyntax") + } + self.valueExpr = expr + } + + /// Creates an assignment with an integer literal value. + public init(_ target: String, _ value: Int) { + self.init(target, .integer(value)) + } + + /// Creates an assignment with a string literal value. + public init(_ target: String, _ value: String) { + self.init(target, .string(value)) } + + /// Creates an assignment with a boolean literal value. + public init(_ target: String, _ value: Bool) { + self.init(target, .boolean(value)) + } + + /// Creates an assignment with a double literal value. + public init(_ target: String, _ value: Double) { + self.init(target, .float(value)) + } + public var syntax: SyntaxProtocol { let left = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(target))) - let right: ExprSyntax - if value.hasPrefix("\"") && value.hasSuffix("\"") || value.contains("\\(") { - right = ExprSyntax( - StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment( - StringSegmentSyntax(content: .stringSegment(String(value.dropFirst().dropLast())))) - ]), - closingQuote: .stringQuoteToken() - )) - } else { - right = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) - } - let assign = ExprSyntax( - AssignmentExprSyntax(equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space))) - return SequenceExprSyntax( - elements: ExprListSyntax([ - left, - assign, - right, - ]) + let right = valueExpr + let assignmentExpr = ExprSyntax( + SequenceExprSyntax( + elements: ExprListSyntax([ + left, + ExprSyntax( + AssignmentExprSyntax(equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space))), + right, + ]) + ) ) + // Wrap the expression as a statement + return StmtSyntax(ExpressionStmtSyntax(expression: assignmentExpr)) } } diff --git a/Sources/SyntaxKit/Break.swift b/Sources/SyntaxKit/Break.swift new file mode 100644 index 0000000..6237c15 --- /dev/null +++ b/Sources/SyntaxKit/Break.swift @@ -0,0 +1,58 @@ +// +// Break.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A `break` statement. +public struct Break: CodeBlock { + private let label: String? + + /// Creates a `break` statement. + /// - Parameter label: An optional label to break from a specific loop or switch. + public init(_ label: String? = nil) { + self.label = label + } + + public var syntax: SyntaxProtocol { + let breakStmt = BreakStmtSyntax( + breakKeyword: .keyword(.break, trailingTrivia: .newline) + ) + + if let label = label { + return StmtSyntax( + breakStmt.with( + \.label, + .identifier(label) + ) + ) + } else { + return StmtSyntax(breakStmt) + } + } +} diff --git a/Sources/SyntaxKit/Call.swift b/Sources/SyntaxKit/Call.swift new file mode 100644 index 0000000..05bdc09 --- /dev/null +++ b/Sources/SyntaxKit/Call.swift @@ -0,0 +1,84 @@ +// +// Call.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// An expression that calls a global function. +public struct Call: CodeBlock { + private let functionName: String + private let parameters: [ParameterExp] + + /// Creates a global function call expression. + /// - Parameter functionName: The name of the function to call. + public init(_ functionName: String) { + self.functionName = functionName + self.parameters = [] + } + + /// Creates a global function call expression with parameters. + /// - Parameters: + /// - functionName: The name of the function to call. + /// - params: A ``ParameterExpBuilder`` that provides the parameters for the function call. + public init(_ functionName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) { + self.functionName = functionName + self.parameters = params() + } + + public var syntax: SyntaxProtocol { + let function = TokenSyntax.identifier(functionName) + let args = LabeledExprListSyntax( + parameters.enumerated().map { index, param in + let expr = param.syntax + if let labeled = expr as? LabeledExprSyntax { + var element = labeled + if index < parameters.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } else if let unlabeled = expr as? ExprSyntax { + return LabeledExprSyntax( + label: nil, + colon: nil, + expression: unlabeled, + trailingComma: index < parameters.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } else { + fatalError("ParameterExp.syntax must return LabeledExprSyntax or ExprSyntax") + } + }) + + return ExprSyntax( + FunctionCallExprSyntax( + calledExpression: ExprSyntax(DeclReferenceExprSyntax(baseName: function)), + leftParen: .leftParenToken(), + arguments: args, + rightParen: .rightParenToken() + )) + } +} diff --git a/Sources/SyntaxKit/Case.swift b/Sources/SyntaxKit/Case.swift index 2ff34da..18c8e59 100644 --- a/Sources/SyntaxKit/Case.swift +++ b/Sources/SyntaxKit/Case.swift @@ -31,43 +31,45 @@ import SwiftSyntax /// A `case` in a `switch` statement with tuple-style patterns. public struct Case: CodeBlock { - private let patterns: [String] + private let patterns: [PatternConvertible] private let body: [CodeBlock] /// Creates a `case` for a `switch` statement. /// - Parameters: /// - patterns: The patterns to match for the case. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. - public init(_ patterns: String..., @CodeBlockBuilderResult content: () -> [CodeBlock]) { + public init(_ patterns: PatternConvertible..., @CodeBlockBuilderResult content: () -> [CodeBlock]) + { self.patterns = patterns self.body = content() } public var switchCaseSyntax: SwitchCaseSyntax { - let patternList = TuplePatternElementListSyntax( - patterns.map { - TuplePatternElementSyntax( - label: nil, - colon: nil, - pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier($0))) - ) - } - ) - let caseItems = SwitchCaseItemListSyntax([ - SwitchCaseItemSyntax( - pattern: TuplePatternSyntax( - leftParen: .leftParenToken(), - elements: patternList, - rightParen: .rightParenToken() - ) - ) - ]) + let caseItems = SwitchCaseItemListSyntax( + patterns.enumerated().map { index, pat in + var item = SwitchCaseItemSyntax(pattern: pat.patternSyntax) + if index < patterns.count - 1 { + item = item.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return item + }) + let statements = CodeBlockItemListSyntax( - body.compactMap { $0.syntax.as(CodeBlockItemSyntax.self) }) + body.compactMap { + var item: CodeBlockItemSyntax? + if let decl = $0.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = $0.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = $0.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + }) let label = SwitchCaseLabelSyntax( caseKeyword: .keyword(.case, trailingTrivia: .space), caseItems: caseItems, - colon: .colonToken() + colon: .colonToken(trailingTrivia: .newline) ) return SwitchCaseSyntax( label: .case(label), diff --git a/Sources/SyntaxKit/Class.swift b/Sources/SyntaxKit/Class.swift index 2c11da2..bf28ff4 100644 --- a/Sources/SyntaxKit/Class.swift +++ b/Sources/SyntaxKit/Class.swift @@ -57,11 +57,11 @@ public struct Class: CodeBlock { } /// Sets the inheritance for the class. - /// - Parameter type: The type to inherit from. + /// - Parameter inheritance: The types to inherit from. /// - Returns: A copy of the class with the inheritance set. - public func inherits(_ type: String) -> Self { + public func inherits(_ inheritance: String...) -> Self { var copy = self - copy.inheritance = [type] + copy.inheritance = inheritance return copy } diff --git a/Sources/SyntaxKit/Continue.swift b/Sources/SyntaxKit/Continue.swift new file mode 100644 index 0000000..26271bc --- /dev/null +++ b/Sources/SyntaxKit/Continue.swift @@ -0,0 +1,58 @@ +// +// Continue.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A `continue` statement. +public struct Continue: CodeBlock { + private let label: String? + + /// Creates a `continue` statement. + /// - Parameter label: An optional label to continue to a specific loop. + public init(_ label: String? = nil) { + self.label = label + } + + public var syntax: SyntaxProtocol { + let continueStmt = ContinueStmtSyntax( + continueKeyword: .keyword(.continue, trailingTrivia: .newline) + ) + + if let label = label { + return StmtSyntax( + continueStmt.with( + \.label, + .identifier(label) + ) + ) + } else { + return StmtSyntax(continueStmt) + } + } +} diff --git a/Sources/SyntaxKit/Default.swift b/Sources/SyntaxKit/Default.swift index 470a7e9..ff38a43 100644 --- a/Sources/SyntaxKit/Default.swift +++ b/Sources/SyntaxKit/Default.swift @@ -52,8 +52,8 @@ public struct Default: CodeBlock { return item?.with(\.trailingTrivia, .newline) }) let label = SwitchDefaultLabelSyntax( - defaultKeyword: .keyword(.default, trailingTrivia: .space), - colon: .colonToken() + defaultKeyword: .keyword(.default), + colon: .colonToken(trailingTrivia: .newline) ) return SwitchCaseSyntax( label: .default(label), diff --git a/Sources/SyntaxKit/Dictionary+LiteralValue.swift b/Sources/SyntaxKit/Dictionary+LiteralValue.swift new file mode 100644 index 0000000..980dc16 --- /dev/null +++ b/Sources/SyntaxKit/Dictionary+LiteralValue.swift @@ -0,0 +1,51 @@ +// +// Dictionary+LiteralValue.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +extension Dictionary: LiteralValue where Key == Int, Value == String { + /// The Swift type name for a dictionary mapping integers to strings. + public var typeName: String { "[Int: String]" } + + /// Renders this dictionary as a Swift literal string with proper escaping. + public var literalString: String { + let elements = self.map { key, value in + // Escape quotes and newlines + let escaped = + value + .replacingOccurrences(of: "\\", with: "\\\\") + .replacingOccurrences(of: "\"", with: "\\\"") + .replacingOccurrences(of: "\n", with: "\\n") + .replacingOccurrences(of: "\r", with: "\\r") + .replacingOccurrences(of: "\t", with: "\\t") + return "\(key): \"\(escaped)\"" + }.joined(separator: ", ") + return "[\(elements)]" + } +} diff --git a/Sources/SyntaxKit/DictionaryLiteral.swift b/Sources/SyntaxKit/DictionaryLiteral.swift new file mode 100644 index 0000000..17200ef --- /dev/null +++ b/Sources/SyntaxKit/DictionaryLiteral.swift @@ -0,0 +1,98 @@ +// +// DictionaryLiteral.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// A dictionary value that can be used as a literal. +public struct DictionaryLiteral: LiteralValue { + let elements: [(Literal, Literal)] + + /// Creates a dictionary with the given key-value pairs. + /// - Parameter elements: The dictionary key-value pairs. + public init(_ elements: [(Literal, Literal)]) { + self.elements = elements + } + + /// The Swift type name for this dictionary. + public var typeName: String { + if elements.isEmpty { + return "[Any: Any]" + } + let keyType = elements.first?.0.typeName ?? "Any" + let valueType = elements.first?.1.typeName ?? "Any" + return "[\(keyType): \(valueType)]" + } + + /// Renders this dictionary as a Swift literal string. + public var literalString: String { + let elementStrings = elements.map { key, value in + let keyString: String + let valueString: String + + switch key { + case .integer(let key): keyString = String(key) + case .float(let key): keyString = String(key) + case .string(let key): keyString = "\"\(key)\"" + case .boolean(let key): keyString = key ? "true" : "false" + case .nil: keyString = "nil" + case .ref(let key): keyString = key + case .tuple(let tupleElements): + let tuple = TupleLiteral(tupleElements) + keyString = tuple.literalString + case .array(let arrayElements): + let array = ArrayLiteral(arrayElements) + keyString = array.literalString + case .dictionary(let dictionaryElements): + let dictionary = DictionaryLiteral(dictionaryElements) + keyString = dictionary.literalString + } + + switch value { + case .integer(let value): valueString = String(value) + case .float(let value): valueString = String(value) + case .string(let value): valueString = "\"\(value)\"" + case .boolean(let value): valueString = value ? "true" : "false" + case .nil: valueString = "nil" + case .ref(let value): valueString = value + case .tuple(let tupleElements): + let tuple = TupleLiteral(tupleElements) + valueString = tuple.literalString + case .array(let arrayElements): + let array = ArrayLiteral(arrayElements) + valueString = array.literalString + case .dictionary(let dictionaryElements): + let dictionary = DictionaryLiteral(dictionaryElements) + valueString = dictionary.literalString + } + + return "\(keyString): \(valueString)" + } + return "[\(elementStrings.joined(separator: ", "))]" + } +} diff --git a/Sources/SyntaxKit/Enum.swift b/Sources/SyntaxKit/Enum.swift index 65a9183..a8c8e52 100644 --- a/Sources/SyntaxKit/Enum.swift +++ b/Sources/SyntaxKit/Enum.swift @@ -33,7 +33,7 @@ import SwiftSyntax public struct Enum: CodeBlock { private let name: String private let members: [CodeBlock] - private var inheritance: String? + private var inheritance: [String] = [] private var attributes: [AttributeInfo] = [] /// Creates an `enum` declaration. @@ -46,11 +46,11 @@ public struct Enum: CodeBlock { } /// Sets the inheritance for the enum. - /// - Parameter type: The type to inherit from. + /// - Parameter inheritance: The types to inherit from. /// - Returns: A copy of the enum with the inheritance set. - public func inherits(_ type: String) -> Self { + public func inherits(_ inheritance: String...) -> Self { var copy = self - copy.inheritance = type + copy.inheritance = inheritance return copy } @@ -70,11 +70,26 @@ public struct Enum: CodeBlock { let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) var inheritanceClause: InheritanceClauseSyntax? - if let inheritance = inheritance { - let inheritedType = InheritedTypeSyntax( - type: IdentifierTypeSyntax(name: .identifier(inheritance))) + if !inheritance.isEmpty { + let inheritedTypes = inheritance.map { type in + InheritedTypeSyntax( + type: IdentifierTypeSyntax(name: .identifier(type))) + } inheritanceClause = InheritanceClauseSyntax( - colon: .colonToken(), inheritedTypes: InheritedTypeListSyntax([inheritedType])) + colon: .colonToken(), + inheritedTypes: InheritedTypeListSyntax( + inheritedTypes.enumerated().map { idx, inherited in + var inheritedType = inherited + if idx < inheritedTypes.count - 1 { + inheritedType = inheritedType.with( + \.trailingComma, + TokenSyntax.commaToken(trailingTrivia: .space) + ) + } + return inheritedType + } + ) + ) } let memberBlock = MemberBlockSyntax( @@ -141,106 +156,3 @@ public struct Enum: CodeBlock { return AttributeListSyntax(attributeElements) } } - -/// A Swift `case` declaration inside an `enum`. -public struct EnumCase: CodeBlock { - private let name: String - private var literalValue: Literal? - - /// Creates a `case` declaration. - /// - Parameter name: The name of the case. - public init(_ name: String) { - self.name = name - self.literalValue = nil - } - - /// Sets the raw value of the case to a Literal. - /// - Parameter value: The literal value. - /// - Returns: A copy of the case with the raw value set. - public func equals(_ value: Literal) -> Self { - var copy = self - copy.literalValue = value - return copy - } - - /// Sets the raw value of the case to a string (for backward compatibility). - /// - Parameter value: The string value. - /// - Returns: A copy of the case with the raw value set. - public func equals(_ value: String) -> Self { - self.equals(.string(value)) - } - - /// Sets the raw value of the case to an integer (for backward compatibility). - /// - Parameter value: The integer value. - /// - Returns: A copy of the case with the raw value set. - public func equals(_ value: Int) -> Self { - self.equals(.integer(value)) - } - - /// Sets the raw value of the case to a float (for backward compatibility). - /// - Parameter value: The float value. - /// - Returns: A copy of the case with the raw value set. - public func equals(_ value: Double) -> Self { - self.equals(.float(value)) - } - - public var syntax: SyntaxProtocol { - let caseKeyword = TokenSyntax.keyword(.case, trailingTrivia: .space) - let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) - - var initializer: InitializerClauseSyntax? - if let literal = literalValue { - switch literal { - case .string(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) - ]), - closingQuote: .stringQuoteToken() - ) - ) - case .float(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: FloatLiteralExprSyntax(literal: .floatLiteral(String(value))) - ) - case .integer(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(value))) - ) - case .nil: - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) - ) - case .boolean(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) - ) - } - } - - return EnumCaseDeclSyntax( - caseKeyword: caseKeyword, - elements: EnumCaseElementListSyntax([ - EnumCaseElementSyntax( - leadingTrivia: .space, - _: nil, - name: identifier, - _: nil, - parameterClause: nil, - _: nil, - rawValue: initializer, - _: nil, - trailingComma: nil, - trailingTrivia: .newline - ) - ]) - ) - } -} diff --git a/Sources/SyntaxKit/EnumCase.swift b/Sources/SyntaxKit/EnumCase.swift new file mode 100644 index 0000000..61c09ee --- /dev/null +++ b/Sources/SyntaxKit/EnumCase.swift @@ -0,0 +1,144 @@ +// +// EnumCase.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift `case` declaration inside an `enum`. +public struct EnumCase: CodeBlock { + private let name: String + private var literalValue: Literal? + + /// Creates a `case` declaration. + /// - Parameter name: The name of the case. + public init(_ name: String) { + self.name = name + self.literalValue = nil + } + + /// Sets the raw value of the case to a Literal. + /// - Parameter value: The literal value. + /// - Returns: A copy of the case with the raw value set. + public func equals(_ value: Literal) -> Self { + var copy = self + copy.literalValue = value + return copy + } + + /// Sets the raw value of the case to a string (for backward compatibility). + /// - Parameter value: The string value. + /// - Returns: A copy of the case with the raw value set. + public func equals(_ value: String) -> Self { + self.equals(.string(value)) + } + + /// Sets the raw value of the case to an integer (for backward compatibility). + /// - Parameter value: The integer value. + /// - Returns: A copy of the case with the raw value set. + public func equals(_ value: Int) -> Self { + self.equals(.integer(value)) + } + + /// Sets the raw value of the case to a float (for backward compatibility). + /// - Parameter value: The float value. + /// - Returns: A copy of the case with the raw value set. + public func equals(_ value: Double) -> Self { + self.equals(.float(value)) + } + + public var syntax: SyntaxProtocol { + let caseKeyword = TokenSyntax.keyword(.case, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) + + var initializer: InitializerClauseSyntax? + if let literal = literalValue { + switch literal { + case .string(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: StringLiteralExprSyntax( + openingQuote: .stringQuoteToken(), + segments: StringLiteralSegmentListSyntax([ + .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) + ]), + closingQuote: .stringQuoteToken() + ) + ) + case .float(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: FloatLiteralExprSyntax(literal: .floatLiteral(String(value))) + ) + case .integer(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(value))) + ) + case .nil: + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) + ) + case .boolean(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) + ) + case .ref(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: DeclReferenceExprSyntax(baseName: .identifier(value)) + ) + case .tuple: + fatalError("Tuple is not supported as a raw value for enum cases.") + case .array: + fatalError("Array is not supported as a raw value for enum cases.") + case .dictionary: + fatalError("Dictionary is not supported as a raw value for enum cases.") + } + } + + return EnumCaseDeclSyntax( + caseKeyword: caseKeyword, + elements: EnumCaseElementListSyntax([ + EnumCaseElementSyntax( + leadingTrivia: .space, + _: nil, + name: identifier, + _: nil, + parameterClause: nil, + _: nil, + rawValue: initializer, + _: nil, + trailingComma: nil, + trailingTrivia: .newline + ) + ]) + ) + } +} diff --git a/Sources/SyntaxKit/ExprCodeBlock.swift b/Sources/SyntaxKit/ExprCodeBlock.swift new file mode 100644 index 0000000..34794ba --- /dev/null +++ b/Sources/SyntaxKit/ExprCodeBlock.swift @@ -0,0 +1,36 @@ +// +// ExprCodeBlock.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A protocol for types that can be represented as an ExprSyntax node. +public protocol ExprCodeBlock { + /// The SwiftSyntax expression representation of the code block. + var exprSyntax: ExprSyntax { get } +} diff --git a/Sources/SyntaxKit/Fallthrough.swift b/Sources/SyntaxKit/Fallthrough.swift new file mode 100644 index 0000000..74cee65 --- /dev/null +++ b/Sources/SyntaxKit/Fallthrough.swift @@ -0,0 +1,44 @@ +// +// Fallthrough.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A `fallthrough` statement. +public struct Fallthrough: CodeBlock { + /// Creates a `fallthrough` statement. + public init() {} + + public var syntax: SyntaxProtocol { + StmtSyntax( + FallthroughStmtSyntax( + fallthroughKeyword: .keyword(.fallthrough, trailingTrivia: .newline) + ) + ) + } +} diff --git a/Sources/SyntaxKit/For.swift b/Sources/SyntaxKit/For.swift new file mode 100644 index 0000000..ed3c963 --- /dev/null +++ b/Sources/SyntaxKit/For.swift @@ -0,0 +1,140 @@ +// +// For.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A `for-in` loop statement. +public struct For: CodeBlock { + private let pattern: any CodeBlock & PatternConvertible + private let sequence: CodeBlock + private let whereClause: CodeBlock? + private let body: [CodeBlock] + + /// Creates a `for-in` loop statement. + /// - Parameters: + /// - pattern: A `CodeBlock` that also conforms to `PatternConvertible` for the loop variable(s). + /// - sequence: A `CodeBlock` that produces the sequence to iterate over. + /// - whereClause: An optional `CodeBlockBuilder` that produces the where clause condition. + /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. + public init( + _ pattern: any CodeBlock & PatternConvertible, + in sequence: CodeBlock, + @CodeBlockBuilderResult where whereClause: () -> [CodeBlock] = { [] }, + @CodeBlockBuilderResult then: () -> [CodeBlock] + ) { + self.pattern = pattern + self.sequence = sequence + let whereBlocks = whereClause() + self.whereClause = whereBlocks.isEmpty ? nil : whereBlocks[0] + self.body = then() + } + + /// Creates a `for-in` loop statement with a closure-based pattern. + /// - Parameters: + /// - pattern: A `CodeBlockBuilder` that produces the pattern for the loop variable(s). + /// - sequence: A `CodeBlock` that produces the sequence to iterate over. + /// - whereClause: An optional `CodeBlockBuilder` that produces the where clause condition. + /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. + public init( + @CodeBlockBuilderResult _ pattern: () -> [CodeBlock], + in sequence: CodeBlock, + @CodeBlockBuilderResult where whereClause: () -> [CodeBlock] = { [] }, + @CodeBlockBuilderResult then: () -> [CodeBlock] + ) { + let patterns = pattern() + guard patterns.count == 1 else { + fatalError("For requires exactly one pattern CodeBlock") + } + guard let patternBlock = patterns[0] as? (any CodeBlock & PatternConvertible) else { + fatalError("For pattern must implement both CodeBlock and PatternConvertible protocols") + } + self.pattern = patternBlock + self.sequence = sequence + let whereBlocks = whereClause() + self.whereClause = whereBlocks.isEmpty ? nil : whereBlocks[0] + self.body = then() + } + + public var syntax: SyntaxProtocol { + // Build the pattern using the PatternConvertible protocol + let patternSyntax = pattern.patternSyntax + + // Build the sequence expression + let sequenceExpr = ExprSyntax( + fromProtocol: sequence.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + + // Build the where clause if present + var whereClauseSyntax: WhereClauseSyntax? + if let whereBlock = whereClause { + let whereExpr = ExprSyntax( + fromProtocol: whereBlock.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + whereClauseSyntax = WhereClauseSyntax( + whereKeyword: .keyword(.where, leadingTrivia: .space, trailingTrivia: .space), + guardResult: whereExpr + ) + } + + // Build the body + let bodyBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax( + body.compactMap { + var item: CodeBlockItemSyntax? + if let decl = $0.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = $0.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = $0.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + }), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + return StmtSyntax( + ForInStmtSyntax( + forKeyword: .keyword(.for, trailingTrivia: .space), + tryKeyword: nil, + awaitKeyword: nil, + caseKeyword: nil, + pattern: patternSyntax, + typeAnnotation: nil, + inKeyword: .keyword(.in, leadingTrivia: .space, trailingTrivia: .space), + sequence: sequenceExpr, + whereClause: whereClauseSyntax, + body: bodyBlock + ) + ) + } +} diff --git a/Sources/SyntaxKit/Guard.swift b/Sources/SyntaxKit/Guard.swift new file mode 100644 index 0000000..40f194f --- /dev/null +++ b/Sources/SyntaxKit/Guard.swift @@ -0,0 +1,139 @@ +// +// Guard.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A `guard … else { … }` statement. +public struct Guard: CodeBlock { + private let conditions: [CodeBlock] + private let elseBody: [CodeBlock] + + /// Creates a `guard` statement. + /// - Parameters: + /// - condition: A builder that returns one or more ``CodeBlock`` items representing the guard conditions. + /// - elseBody: Builder that produces the statements inside the `else` block. + public init( + @CodeBlockBuilderResult _ condition: () -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] + ) { + let allConditions = condition() + guard !allConditions.isEmpty else { + fatalError("Guard requires at least one condition CodeBlock") + } + self.conditions = allConditions + self.elseBody = elseBody() + } + + /// Convenience initializer that accepts a single condition ``CodeBlock``. + public init( + _ condition: CodeBlock, + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] + ) { + self.init({ condition }, else: elseBody) + } + + public var syntax: SyntaxProtocol { + // MARK: Build conditions list (mirror implementation from `If`) + let condList = ConditionElementListSyntax( + conditions.enumerated().map { index, block in + let needsComma = index < conditions.count - 1 + func appendComma(_ element: ConditionElementSyntax) -> ConditionElementSyntax { + needsComma ? element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) : element + } + + if let letCond = block as? Let { + let element = ConditionElementSyntax( + condition: .optionalBinding( + OptionalBindingConditionSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: IdentifierPatternSyntax(identifier: .identifier(letCond.name)), + initializer: InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: letCond.value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + ) + ) + ) + ) + return appendComma(element) + } else { + let element = ConditionElementSyntax( + condition: .expression( + ExprSyntax( + fromProtocol: block.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")))) + ) + return appendComma(element) + } + } + ) + + // MARK: Build else body code block + var elseItems: [CodeBlockItemSyntax] = elseBody.compactMap { block in + if let decl = block.syntax.as(DeclSyntax.self) { + return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) + } else if let expr = block.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)).with(\.trailingTrivia, .newline) + } else if let stmt = block.syntax.as(StmtSyntax.self) { + return CodeBlockItemSyntax(item: .stmt(stmt)).with(\.trailingTrivia, .newline) + } + return nil + } + + // Automatically append a bare `return` if the user didn't provide a terminating statement. + let containsReturn = elseItems.contains { item in + if case .stmt(let stmt) = item.item { + return stmt.is(ReturnStmtSyntax.self) + } + return false + } + if !containsReturn { + let retStmt = ReturnStmtSyntax(returnKeyword: .keyword(.return)) + elseItems.append( + CodeBlockItemSyntax(item: .stmt(StmtSyntax(retStmt))).with(\.trailingTrivia, .newline) + ) + } + + let elseBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax(elseItems), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + // Build and return GuardStmtSyntax wrapped in `StmtSyntax` + return StmtSyntax( + GuardStmtSyntax( + guardKeyword: .keyword(.guard, trailingTrivia: .space), + conditions: condList, + elseKeyword: .keyword(.else, leadingTrivia: .space, trailingTrivia: .space), + body: elseBlock + ) + ) + } +} diff --git a/Sources/SyntaxKit/If.swift b/Sources/SyntaxKit/If.swift index 53e7bd5..8d8c4e5 100644 --- a/Sources/SyntaxKit/If.swift +++ b/Sources/SyntaxKit/If.swift @@ -31,47 +31,77 @@ import SwiftSyntax /// An `if` statement. public struct If: CodeBlock { - private let condition: CodeBlock + private let conditions: [CodeBlock] private let body: [CodeBlock] private let elseBody: [CodeBlock]? - /// Creates an `if` statement. + /// Creates an `if` statement with optional `else`. /// - Parameters: - /// - condition: The condition to evaluate. This can be a ``Let`` for optional binding. - /// - then: A ``CodeBlockBuilder`` that provides the body of the `if` block. - /// - elseBody: A ``CodeBlockBuilder`` that provides the body of the `else` block, if any. + /// - condition: A single `CodeBlock` produced by the builder that describes the `if` condition. + /// - then: Builder that produces the body for the `if` branch. + /// - elseBody: Builder that produces the body for the `else` branch. The body may contain + /// nested `If` instances (representing `else if`) and/or a ``Then`` block for the + /// final `else` statements. public init( - _ condition: CodeBlock, @CodeBlockBuilderResult then: () -> [CodeBlock], - else elseBody: (() -> [CodeBlock])? = nil + @CodeBlockBuilderResult _ condition: () -> [CodeBlock], + @CodeBlockBuilderResult then: () -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } ) { - self.condition = condition + let allConditions = condition() + guard !allConditions.isEmpty else { + fatalError("If requires at least one condition CodeBlock") + } + self.conditions = allConditions self.body = then() - self.elseBody = elseBody?() + let generatedElse = elseBody() + self.elseBody = generatedElse.isEmpty ? nil : generatedElse + } + + /// Convenience initializer that keeps the previous API: pass the condition directly. + public init( + _ condition: CodeBlock, + @CodeBlockBuilderResult then: () -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } + ) { + self.init({ condition }, then: then, else: elseBody) } public var syntax: SyntaxProtocol { - let cond: ConditionElementSyntax - if let letCond = condition as? Let { - cond = ConditionElementSyntax( - condition: .optionalBinding( - OptionalBindingConditionSyntax( - bindingSpecifier: .keyword(.let, trailingTrivia: .space), - pattern: IdentifierPatternSyntax(identifier: .identifier(letCond.name)), - initializer: InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(letCond.value))) + // Build list of ConditionElements from all provided conditions + let condList = ConditionElementListSyntax( + conditions.enumerated().map { index, block in + let needsComma = index < conditions.count - 1 + + func appendComma(_ element: ConditionElementSyntax) -> ConditionElementSyntax { + needsComma ? element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) : element + } + + if let letCond = block as? Let { + let element = ConditionElementSyntax( + condition: .optionalBinding( + OptionalBindingConditionSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: IdentifierPatternSyntax(identifier: .identifier(letCond.name)), + initializer: InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: letCond.value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + ) + ) ) ) - ) - ) - } else { - cond = ConditionElementSyntax( - condition: .expression( - ExprSyntax( - fromProtocol: condition.syntax.as(ExprSyntax.self) - ?? DeclReferenceExprSyntax(baseName: .identifier("")))) - ) - } + return appendComma(element) + } else { + let element = ConditionElementSyntax( + condition: .expression( + ExprSyntax( + fromProtocol: block.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")))) + ) + return appendComma(element) + } + } + ) let bodyBlock = CodeBlockSyntax( leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), statements: CodeBlockItemListSyntax( @@ -88,31 +118,93 @@ public struct If: CodeBlock { }), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) - let elseBlock = elseBody.map { - IfExprSyntax.ElseBody( - CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - statements: CodeBlockItemListSyntax( - $0.compactMap { - var item: CodeBlockItemSyntax? - if let decl = $0.syntax.as(DeclSyntax.self) { - item = CodeBlockItemSyntax(item: .decl(decl)) - } else if let expr = $0.syntax.as(ExprSyntax.self) { - item = CodeBlockItemSyntax(item: .expr(expr)) - } else if let stmt = $0.syntax.as(StmtSyntax.self) { - item = CodeBlockItemSyntax(item: .stmt(stmt)) + // swiftlint:disable:next closure_body_length + let elseBlock: IfExprSyntax.ElseBody? = { + guard let elseBlocks = elseBody else { return nil } + + // Build a chained else-if structure if the builder provided If blocks. + var current: SyntaxProtocol? + + for block in elseBlocks.reversed() { + switch block { + case let thenBlock as Then: + // Leaf `else` – produce a code-block. + let stmts = CodeBlockItemListSyntax( + thenBlock.body.compactMap { element in + if let decl = element.syntax.as(DeclSyntax.self) { + return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) + } else if let expr = element.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)).with(\.trailingTrivia, .newline) + } else if let stmt = element.syntax.as(StmtSyntax.self) { + return CodeBlockItemSyntax(item: .stmt(stmt)).with(\.trailingTrivia, .newline) } - return item?.with(\.trailingTrivia, .newline) - }), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - )) - } + return nil + }) + let codeBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: stmts, + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + current = codeBlock as SyntaxProtocol + + case let ifBlock as If: + guard var ifExpr = ifBlock.syntax.as(IfExprSyntax.self) else { continue } + if let nested = current { + let elseChoice: IfExprSyntax.ElseBody + if let cb = nested.as(CodeBlockSyntax.self) { + elseChoice = IfExprSyntax.ElseBody(cb) + } else if let nestedIf = nested.as(IfExprSyntax.self) { + elseChoice = IfExprSyntax.ElseBody(nestedIf) + } else { + continue + } + + ifExpr = + ifExpr + .with(\.elseKeyword, .keyword(.else, leadingTrivia: .space, trailingTrivia: .space)) + .with(\.elseBody, elseChoice) + } + current = ifExpr as SyntaxProtocol + + default: + // Treat any other CodeBlock as part of a final code-block + let item: CodeBlockItemSyntax? + if let decl = block.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = block.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = block.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } else { + item = nil + } + if let itm = item { + let codeBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax([itm.with(\.trailingTrivia, .newline)]), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + current = codeBlock as SyntaxProtocol + } + } + } + + if let final = current { + if let cb = final.as(CodeBlockSyntax.self) { + return IfExprSyntax.ElseBody(cb) + } else if let ifExpr = final.as(IfExprSyntax.self) { + return IfExprSyntax.ElseBody(ifExpr) + } + } + return nil + }() return ExprSyntax( IfExprSyntax( ifKeyword: .keyword(.if, trailingTrivia: .space), - conditions: ConditionElementListSyntax([cond]), + conditions: condList, body: bodyBlock, - elseKeyword: elseBlock != nil ? .keyword(.else, trailingTrivia: .space) : nil, + elseKeyword: elseBlock != nil + ? .keyword(.else, leadingTrivia: .space, trailingTrivia: .space) : nil, elseBody: elseBlock ) ) diff --git a/Sources/SyntaxKit/Init.swift b/Sources/SyntaxKit/Init.swift index c94a9e8..fb9000e 100644 --- a/Sources/SyntaxKit/Init.swift +++ b/Sources/SyntaxKit/Init.swift @@ -30,22 +30,23 @@ import SwiftSyntax /// An initializer expression. -public struct Init: CodeBlock { +public struct Init: CodeBlock, ExprCodeBlock { private let type: String - private let parameters: [Parameter] + private let parameters: [ParameterExp] /// Creates an initializer expression. /// - Parameters: /// - type: The type to initialize. - /// - params: A ``ParameterBuilder`` that provides the parameters for the initializer. - public init(_ type: String, @ParameterBuilderResult _ params: () -> [Parameter]) { + /// - params: A ``ParameterExpBuilder`` that provides the parameters for the initializer. + public init(_ type: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) { self.type = type self.parameters = params() } - public var syntax: SyntaxProtocol { - let args = TupleExprElementListSyntax( + + public var exprSyntax: ExprSyntax { + let args = LabeledExprListSyntax( parameters.enumerated().compactMap { index, param in - guard let element = param.syntax as? TupleExprElementSyntax else { + guard let element = param.syntax as? LabeledExprSyntax else { return nil } if index < parameters.count - 1 { @@ -57,8 +58,12 @@ public struct Init: CodeBlock { FunctionCallExprSyntax( calledExpression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(type))), leftParen: .leftParenToken(), - argumentList: args, + arguments: args, rightParen: .rightParenToken() )) } + + public var syntax: SyntaxProtocol { + exprSyntax + } } diff --git a/Sources/SyntaxKit/Let.swift b/Sources/SyntaxKit/Let.swift index 354a2d7..f6ff30d 100644 --- a/Sources/SyntaxKit/Let.swift +++ b/Sources/SyntaxKit/Let.swift @@ -32,16 +32,26 @@ import SwiftSyntax /// A Swift `let` declaration for use in an `if` statement. public struct Let: CodeBlock { internal let name: String - internal let value: String + internal let value: CodeBlock /// Creates a `let` declaration for an `if` statement. /// - Parameters: /// - name: The name of the constant. /// - value: The value to assign to the constant. - public init(_ name: String, _ value: String) { + public init(_ name: String, _ value: CodeBlock) { self.name = name self.value = value } + + /// Creates a `let` declaration for an `if` statement with a string value. + /// - Parameters: + /// - name: The name of the constant. + /// - value: The string value to assign to the constant. + public init(_ name: String, _ value: String) { + self.name = name + self.value = VariableExp(value) + } + public var syntax: SyntaxProtocol { CodeBlockItemSyntax( item: .decl( @@ -53,7 +63,8 @@ public struct Let: CodeBlock { pattern: IdentifierPatternSyntax(identifier: .identifier(name)), initializer: InitializerClauseSyntax( equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) + value: value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) ) ) ]) diff --git a/Sources/SyntaxKit/Literal+Convenience.swift b/Sources/SyntaxKit/Literal+Convenience.swift new file mode 100644 index 0000000..b7c024f --- /dev/null +++ b/Sources/SyntaxKit/Literal+Convenience.swift @@ -0,0 +1,54 @@ +// +// Literal+Convenience.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +// MARK: - Convenience Methods + +extension Literal { + /// Creates a tuple literal from an array of optional literals (for patterns with wildcards). + public static func tuplePattern(_ elements: [Literal?]) -> Literal { + .tuple(elements) + } + + /// Creates an integer literal. + public static func int(_ value: Int) -> Literal { + .integer(value) + } + + /// Converts a Literal.tuple to a TupleLiteral for use in Variable declarations. + public var asTupleLiteral: TupleLiteral? { + switch self { + case .tuple(let elements): + return TupleLiteral(elements) + default: + return nil + } + } +} diff --git a/Sources/SyntaxKit/Literal+ExprCodeBlock.swift b/Sources/SyntaxKit/Literal+ExprCodeBlock.swift new file mode 100644 index 0000000..8e96d14 --- /dev/null +++ b/Sources/SyntaxKit/Literal+ExprCodeBlock.swift @@ -0,0 +1,117 @@ +// +// Literal+ExprCodeBlock.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +// MARK: - ExprCodeBlock conformance + +extension Literal: ExprCodeBlock { + public var exprSyntax: ExprSyntax { + switch self { + case .string(let value): + return ExprSyntax( + StringLiteralExprSyntax( + openingQuote: .stringQuoteToken(), + segments: .init([ + .stringSegment(.init(content: .stringSegment(value))) + ]), + closingQuote: .stringQuoteToken() + )) + case .float(let value): + return ExprSyntax(FloatLiteralExprSyntax(literal: .floatLiteral(String(value)))) + case .integer(let value): + return ExprSyntax(IntegerLiteralExprSyntax(digits: .integerLiteral(String(value)))) + case .nil: + return ExprSyntax(NilLiteralExprSyntax(nilKeyword: .keyword(.nil))) + case .boolean(let value): + return ExprSyntax( + BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false))) + case .ref(let value): + return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) + case .tuple(let elements): + let tupleElements = TupleExprElementListSyntax( + elements.enumerated().map { index, element in + let elementExpr: ExprSyntax + if let element = element { + elementExpr = element.exprSyntax + } else { + // Wildcard pattern - use underscore + elementExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_"))) + } + return TupleExprElementSyntax( + label: nil, + colon: nil, + expression: elementExpr, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return ExprSyntax( + TupleExprSyntax( + leftParen: .leftParenToken(), + elements: tupleElements, + rightParen: .rightParenToken() + )) + case .array(let elements): + let arrayElements = ArrayElementListSyntax( + elements.enumerated().map { index, element in + ArrayElementSyntax( + expression: element.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return ExprSyntax(ArrayExprSyntax(elements: arrayElements)) + case .dictionary(let elements): + if elements.isEmpty { + // Empty dictionary should generate [:] + return ExprSyntax( + DictionaryExprSyntax( + leftSquare: .leftSquareToken(), + content: .colon(.colonToken(leadingTrivia: .init(), trailingTrivia: .init())), + rightSquare: .rightSquareToken() + )) + } else { + let dictionaryElements = DictionaryElementListSyntax( + elements.enumerated().map { index, keyValue in + let (key, value) = keyValue + return DictionaryElementSyntax( + keyExpression: key.exprSyntax, + colon: .colonToken(), + valueExpression: value.exprSyntax, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return ExprSyntax(DictionaryExprSyntax(content: .elements(dictionaryElements))) + } + } + } +} diff --git a/Sources/SyntaxKit/Literal.swift b/Sources/SyntaxKit/Literal.swift index 0cec486..0a2dbee 100644 --- a/Sources/SyntaxKit/Literal.swift +++ b/Sources/SyntaxKit/Literal.swift @@ -29,15 +29,6 @@ import SwiftSyntax -/// A protocol for types that can be represented as literal values in Swift code. -public protocol LiteralValue { - /// The Swift type name for this literal value. - var typeName: String { get } - - /// Renders this value as a Swift literal string. - var literalString: String { get } -} - /// A literal value. public enum Literal: CodeBlock { /// A string literal. @@ -50,7 +41,60 @@ public enum Literal: CodeBlock { case `nil` /// A boolean literal. case boolean(Bool) + /// A reference to a variable or identifier (outputs without quotes). + case ref(String) + /// A tuple literal. + case tuple([Literal?]) + /// An array literal. + case array([Literal]) + /// A dictionary literal. + case dictionary([(Literal, Literal)]) + + /// The Swift type name for this literal. + public var typeName: String { + switch self { + case .string: return "String" + case .float: return "Double" + case .integer: return "Int" + case .nil: return "Any?" + case .boolean: return "Bool" + case .ref: return "Any" + case .tuple(let elements): + let elementTypes = elements.map { element in + if let element = element { + switch element { + case .integer: return "Int" + case .float: return "Double" + case .string: return "String" + case .boolean: return "Bool" + case .nil: return "Any?" + case .ref: return "Any" + case .tuple: return "Any" + case .array: return "Any" + case .dictionary: return "Any" + } + } else { + return "Any" + } + } + return "(\(elementTypes.joined(separator: ", ")))" + case .array(let elements): + if elements.isEmpty { + return "[Any]" + } + let elementType = elements.first?.typeName ?? "Any" + return "[\(elementType)]" + case .dictionary(let elements): + if elements.isEmpty { + return "[Any: Any]" + } + let keyType = elements.first?.0.typeName ?? "Any" + let valueType = elements.first?.1.typeName ?? "Any" + return "[\(keyType): \(valueType)]" + } + } + /// The SwiftSyntax representation of this literal. public var syntax: SyntaxProtocol { switch self { case .string(let value): @@ -70,46 +114,68 @@ public enum Literal: CodeBlock { return NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) case .boolean(let value): return BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) + case .ref(let value): + return DeclReferenceExprSyntax(baseName: .identifier(value)) + case .tuple(let elements): + let tupleElements = TupleExprElementListSyntax( + elements.enumerated().map { index, element in + let elementExpr: ExprSyntax + if let element = element { + elementExpr = + element.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } else { + // Wildcard pattern - use underscore + elementExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_"))) + } + return TupleExprElementSyntax( + label: nil, + colon: nil, + expression: elementExpr, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return TupleExprSyntax( + leftParen: .leftParenToken(), + elements: tupleElements, + rightParen: .rightParenToken() + ) + case .array(let elements): + let arrayElements = ArrayElementListSyntax( + elements.enumerated().map { index, element in + ArrayElementSyntax( + expression: element.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return ArrayExprSyntax(elements: arrayElements) + case .dictionary(let elements): + if elements.isEmpty { + // Empty dictionary should generate [:] + return DictionaryExprSyntax( + leftSquare: .leftSquareToken(), + content: .colon(.colonToken(leadingTrivia: .init(), trailingTrivia: .init())), + rightSquare: .rightSquareToken() + ) + } else { + let dictionaryElements = DictionaryElementListSyntax( + elements.enumerated().map { index, keyValue in + let (key, value) = keyValue + return DictionaryElementSyntax( + keyExpression: key.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))), + colon: .colonToken(), + valueExpression: value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return DictionaryExprSyntax(content: .elements(dictionaryElements)) + } } } } - -// MARK: - LiteralValue Implementations - -extension Array: LiteralValue where Element == String { - public var typeName: String { "[String]" } - - public var literalString: String { - let elements = self.map { element in - // Escape quotes and newlines - let escaped = - element - .replacingOccurrences(of: "\\", with: "\\\\") - .replacingOccurrences(of: "\"", with: "\\\"") - .replacingOccurrences(of: "\n", with: "\\n") - .replacingOccurrences(of: "\r", with: "\\r") - .replacingOccurrences(of: "\t", with: "\\t") - return "\"\(escaped)\"" - }.joined(separator: ", ") - return "[\(elements)]" - } -} - -extension Dictionary: LiteralValue where Key == Int, Value == String { - public var typeName: String { "[Int: String]" } - - public var literalString: String { - let elements = self.map { key, value in - // Escape quotes and newlines - let escaped = - value - .replacingOccurrences(of: "\\", with: "\\\\") - .replacingOccurrences(of: "\"", with: "\\\"") - .replacingOccurrences(of: "\n", with: "\\n") - .replacingOccurrences(of: "\r", with: "\\r") - .replacingOccurrences(of: "\t", with: "\\t") - return "\(key): \"\(escaped)\"" - }.joined(separator: ", ") - return "[\(elements)]" - } -} diff --git a/Sources/SyntaxKit/LiteralValue.swift b/Sources/SyntaxKit/LiteralValue.swift new file mode 100644 index 0000000..afb8cfe --- /dev/null +++ b/Sources/SyntaxKit/LiteralValue.swift @@ -0,0 +1,39 @@ +// +// LiteralValue.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// A protocol for types that can be represented as literal values in Swift code. +public protocol LiteralValue { + /// The Swift type name for this literal value. + var typeName: String { get } + + /// Renders this value as a Swift literal string. + var literalString: String { get } +} diff --git a/Sources/SyntaxKit/Parameter.swift b/Sources/SyntaxKit/Parameter.swift index 3090d6c..3046692 100644 --- a/Sources/SyntaxKit/Parameter.swift +++ b/Sources/SyntaxKit/Parameter.swift @@ -52,6 +52,15 @@ public struct Parameter: CodeBlock { self.isUnnamed = isUnnamed } + /// Creates an unlabeled parameter for function calls or initializers. + /// - Parameter value: The value of the parameter. + public init(unlabeled value: String) { + self.name = "" + self.type = "" + self.defaultValue = value + self.isUnnamed = true + } + /// Adds an attribute to the parameter declaration. /// - Parameters: /// - attribute: The attribute name (without the @ symbol). diff --git a/Sources/SyntaxKit/ParameterExp.swift b/Sources/SyntaxKit/ParameterExp.swift index 87294a8..90539a8 100644 --- a/Sources/SyntaxKit/ParameterExp.swift +++ b/Sources/SyntaxKit/ParameterExp.swift @@ -32,25 +32,48 @@ import SwiftSyntax /// A parameter for a function call. public struct ParameterExp: CodeBlock { internal let name: String - internal let value: String + internal let value: CodeBlock /// Creates a parameter for a function call. /// - Parameters: /// - name: The name of the parameter. /// - value: The value of the parameter. + public init(name: String, value: CodeBlock) { + self.name = name + self.value = value + } + + /// Creates a parameter for a function call with a string value. + /// - Parameters: + /// - name: The name of the parameter. + /// - value: The string value of the parameter. public init(name: String, value: String) { self.name = name + self.value = VariableExp(value) + } + + /// Convenience initializer for unlabeled parameter with a CodeBlock value. + public init(unlabeled value: CodeBlock) { + self.name = "" self.value = value } + /// Convenience initializer for unlabeled parameter with a String value. + public init(unlabeled value: String) { + self.name = "" + self.value = VariableExp(value) + } + public var syntax: SyntaxProtocol { if name.isEmpty { - return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) + return value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) } else { return LabeledExprSyntax( label: .identifier(name), colon: .colonToken(), - expression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) + expression: value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) ) } } diff --git a/Sources/SyntaxKit/PatternConvertible.swift b/Sources/SyntaxKit/PatternConvertible.swift new file mode 100644 index 0000000..7e502e4 --- /dev/null +++ b/Sources/SyntaxKit/PatternConvertible.swift @@ -0,0 +1,127 @@ +// +// PatternConvertible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// Types that can be turned into a `PatternSyntax` suitable for a `switch` case pattern. +public protocol PatternConvertible { + /// SwiftSyntax representation of the pattern. + var patternSyntax: PatternSyntax { get } +} + +// MARK: - Literal conformance + +extension Literal: PatternConvertible { + /// SwiftSyntax representation of the literal as a pattern. + public var patternSyntax: PatternSyntax { + guard let expr = self.syntax.as(ExprSyntax.self) else { + fatalError("Literal.syntax did not return ExprSyntax") + } + return PatternSyntax(ExpressionPatternSyntax(expression: expr)) + } +} + +// MARK: - Int conformance + +extension Int: PatternConvertible { + /// SwiftSyntax representation of the integer as a pattern. + public var patternSyntax: PatternSyntax { + let expr = ExprSyntax(IntegerLiteralExprSyntax(literal: .integerLiteral(String(self)))) + return PatternSyntax(ExpressionPatternSyntax(expression: expr)) + } +} + +// MARK: - Ranges + +extension Swift.Range: PatternConvertible where Bound == Int { + /// SwiftSyntax representation of the range as a pattern. + public var patternSyntax: PatternSyntax { + let lhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.lowerBound)))) + let op = ExprSyntax(BinaryOperatorExprSyntax(operator: .binaryOperator("..<"))) + let rhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.upperBound)))) + let seq = SequenceExprSyntax(elements: ExprListSyntax([lhs, op, rhs])) + return PatternSyntax(ExpressionPatternSyntax(expression: ExprSyntax(seq))) + } +} + +extension Swift.ClosedRange: PatternConvertible where Bound == Int { + /// SwiftSyntax representation of the closed range as a pattern. + public var patternSyntax: PatternSyntax { + let lhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.lowerBound)))) + let op = ExprSyntax(BinaryOperatorExprSyntax(operator: .binaryOperator("..."))) + let rhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.upperBound)))) + let seq = SequenceExprSyntax(elements: ExprListSyntax([lhs, op, rhs])) + return PatternSyntax(ExpressionPatternSyntax(expression: ExprSyntax(seq))) + } +} + +// MARK: - String identifiers + +extension String: PatternConvertible { + /// SwiftSyntax representation of the string as an identifier pattern. + public var patternSyntax: PatternSyntax { + PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(self))) + } +} + +// MARK: - Let binding pattern + +/// A `let` binding pattern for switch cases. +public struct LetBindingPattern: PatternConvertible { + private let identifier: String + + internal init(identifier: String) { + self.identifier = identifier + } + + /// SwiftSyntax representation of the let binding pattern. + public var patternSyntax: PatternSyntax { + PatternSyntax( + ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(identifier))) + ) + ) + } +} + +/// Namespace for pattern creation utilities. +public enum Pattern { + /// Creates a `let` binding pattern for switch cases. + /// - Parameter identifier: The name of the variable to bind. + /// - Returns: A pattern that binds the value to the given identifier. + public static func `let`(_ identifier: String) -> LetBindingPattern { + LetBindingPattern(identifier: identifier) + } +} diff --git a/Sources/SyntaxKit/PlusAssign.swift b/Sources/SyntaxKit/PlusAssign.swift index 8b79cc8..2ad0bab 100644 --- a/Sources/SyntaxKit/PlusAssign.swift +++ b/Sources/SyntaxKit/PlusAssign.swift @@ -32,33 +32,39 @@ import SwiftSyntax /// A `+=` expression. public struct PlusAssign: CodeBlock { private let target: String - private let value: String + private let valueExpr: ExprSyntax - /// Creates a `+=` expression. - /// - Parameters: - /// - target: The variable to assign to. - /// - value: The value to add and assign. - public init(_ target: String, _ value: String) { + /// Creates a `+=` expression with a literal value. + public init(_ target: String, _ literal: Literal) { self.target = target - self.value = value + guard let expr = literal.syntax.as(ExprSyntax.self) else { + fatalError("Literal.syntax did not produce ExprSyntax") + } + self.valueExpr = expr + } + + /// Creates a `+=` expression with an integer literal value. + public init(_ target: String, _ value: Int) { + self.init(target, .integer(value)) + } + + /// Creates a `+=` expression with a string literal value. + public init(_ target: String, _ value: String) { + self.init(target, .string(value)) + } + + /// Creates a `+=` expression with a boolean literal value. + public init(_ target: String, _ value: Bool) { + self.init(target, .boolean(value)) + } + + /// Creates a `+=` expression with a double literal value. + public init(_ target: String, _ value: Double) { + self.init(target, .float(value)) } public var syntax: SyntaxProtocol { let left = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(target))) - let right: ExprSyntax - if value.hasPrefix("\"") && value.hasSuffix("\"") || value.contains("\\(") { - right = ExprSyntax( - StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment( - StringSegmentSyntax(content: .stringSegment(String(value.dropFirst().dropLast())))) - ]), - closingQuote: .stringQuoteToken() - )) - } else { - right = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) - } let assign = ExprSyntax( BinaryOperatorExprSyntax( operator: .binaryOperator("+=", leadingTrivia: .space, trailingTrivia: .space))) @@ -66,7 +72,7 @@ public struct PlusAssign: CodeBlock { elements: ExprListSyntax([ left, assign, - right, + valueExpr, ]) ) } diff --git a/Sources/SyntaxKit/Struct.swift b/Sources/SyntaxKit/Struct.swift index 48e95ce..cbf7b76 100644 --- a/Sources/SyntaxKit/Struct.swift +++ b/Sources/SyntaxKit/Struct.swift @@ -34,7 +34,7 @@ public struct Struct: CodeBlock { private let name: String private let members: [CodeBlock] private var genericParameter: String? - private var inheritance: String? + private var inheritance: [String] = [] private var attributes: [AttributeInfo] = [] /// Creates a `struct` declaration. @@ -56,9 +56,9 @@ public struct Struct: CodeBlock { } /// Sets the inheritance for the struct. - /// - Parameter inheritance: The type to inherit from. + /// - Parameter inheritance: The types to inherit from. /// - Returns: A copy of the struct with the inheritance set. - public func inherits(_ inheritance: String) -> Self { + public func inherits(_ inheritance: String...) -> Self { var copy = self copy.inheritance = inheritance return copy @@ -93,11 +93,26 @@ public struct Struct: CodeBlock { } var inheritanceClause: InheritanceClauseSyntax? - if let inheritance = inheritance { - let inheritedType = InheritedTypeSyntax( - type: IdentifierTypeSyntax(name: .identifier(inheritance))) + if !inheritance.isEmpty { + let inheritedTypes = inheritance.map { type in + InheritedTypeSyntax( + type: IdentifierTypeSyntax(name: .identifier(type))) + } inheritanceClause = InheritanceClauseSyntax( - colon: .colonToken(), inheritedTypes: InheritedTypeListSyntax([inheritedType])) + colon: .colonToken(), + inheritedTypes: InheritedTypeListSyntax( + inheritedTypes.enumerated().map { idx, inherited in + var inheritedType = inherited + if idx < inheritedTypes.count - 1 { + inheritedType = inheritedType.with( + \.trailingComma, + TokenSyntax.commaToken(trailingTrivia: .space) + ) + } + return inheritedType + } + ) + ) } let memberBlock = MemberBlockSyntax( diff --git a/Sources/SyntaxKit/Switch.swift b/Sources/SyntaxKit/Switch.swift index b03f7fb..bd44369 100644 --- a/Sources/SyntaxKit/Switch.swift +++ b/Sources/SyntaxKit/Switch.swift @@ -31,21 +31,34 @@ import SwiftSyntax /// A `switch` statement. public struct Switch: CodeBlock { - private let expression: String + private let expression: CodeBlock private let cases: [CodeBlock] /// Creates a `switch` statement. /// - Parameters: /// - expression: The expression to switch on. /// - content: A ``CodeBlockBuilder`` that provides the cases for the switch. - public init(_ expression: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + public init(_ expression: CodeBlock, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { self.expression = expression self.cases = content() } + /// Convenience initializer that accepts a string expression. + /// - Parameters: + /// - expression: The string expression to switch on. + /// - content: A ``CodeBlockBuilder`` that provides the cases for the switch. + public init(_ expression: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.expression = VariableExp(expression) + self.cases = content() + } + public var syntax: SyntaxProtocol { - let expr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(expression))) + let expr = ExprSyntax( + fromProtocol: expression.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) let casesArr: [SwitchCaseSyntax] = self.cases.compactMap { + if let tupleCase = $0 as? Case { return tupleCase.switchCaseSyntax } if let switchCase = $0 as? SwitchCase { return switchCase.switchCaseSyntax } if let switchDefault = $0 as? Default { return switchDefault.switchCaseSyntax } return nil diff --git a/Sources/SyntaxKit/SwitchCase.swift b/Sources/SyntaxKit/SwitchCase.swift index 1d219b4..ff7a3d6 100644 --- a/Sources/SyntaxKit/SwitchCase.swift +++ b/Sources/SyntaxKit/SwitchCase.swift @@ -31,44 +31,110 @@ import SwiftSyntax /// A `case` in a `switch` statement. public struct SwitchCase: CodeBlock { - private let patterns: [String] + private let patterns: [Any] private let body: [CodeBlock] /// Creates a `case` for a `switch` statement. /// - Parameters: - /// - patterns: The patterns to match for the case. + /// - patterns: The patterns to match for the case. Can be `PatternConvertible`, `CodeBlock`, or `SwitchLet` for value binding. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. - public init(_ patterns: String..., @CodeBlockBuilderResult content: () -> [CodeBlock]) { + public init(_ patterns: Any..., @CodeBlockBuilderResult content: () -> [CodeBlock]) { self.patterns = patterns self.body = content() } + /// Creates a `case` for a `switch` statement with a builder closure for the conditional. + /// - Parameters: + /// - conditional: A ``CodeBlockBuilder`` that provides the conditional patterns for the case. + /// - content: A ``CodeBlockBuilder`` that provides the body of the case. + public init( + @CodeBlockBuilderResult conditional: () -> [Any], + @CodeBlockBuilderResult content: () -> [CodeBlock] + ) { + self.patterns = conditional() + self.body = content() + } + public var switchCaseSyntax: SwitchCaseSyntax { let caseItems = SwitchCaseItemListSyntax( - patterns.enumerated().map { index, pattern in - var item = SwitchCaseItemSyntax( - pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(pattern))) - ) + patterns.enumerated().compactMap { index, pattern -> SwitchCaseItemSyntax? in + let patternSyntax: PatternSyntax + + if let patternConvertible = pattern as? PatternConvertible { + patternSyntax = patternConvertible.patternSyntax + } else if let variableExp = pattern as? VariableExp { + // Handle VariableExp specially - convert to identifier pattern + patternSyntax = PatternSyntax( + IdentifierPatternSyntax(identifier: .identifier(variableExp.name))) + } else if let codeBlock = pattern as? CodeBlock { + // Convert CodeBlock to expression pattern + let expr = ExprSyntax( + fromProtocol: codeBlock.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + patternSyntax = PatternSyntax(ExpressionPatternSyntax(expression: expr)) + } else { + return nil + } + + var item = SwitchCaseItemSyntax(pattern: patternSyntax) if index < patterns.count - 1 { item = item.with(\.trailingComma, .commaToken(trailingTrivia: .space)) } return item }) - let statements = CodeBlockItemListSyntax( - body.compactMap { - var item: CodeBlockItemSyntax? - if let decl = $0.syntax.as(DeclSyntax.self) { - item = CodeBlockItemSyntax(item: .decl(decl)) - } else if let expr = $0.syntax.as(ExprSyntax.self) { - item = CodeBlockItemSyntax(item: .expr(expr)) - } else if let stmt = $0.syntax.as(StmtSyntax.self) { - item = CodeBlockItemSyntax(item: .stmt(stmt)) - } - return item?.with(\.trailingTrivia, .newline) - }) + + // Handle special case for multiple conditionals with let binding and where clause + var finalCaseItems = caseItems + if patterns.count >= 2 { + // Check if we have a let binding followed by an expression (where clause) + if let firstPattern = patterns.first as? SwitchLet, + let secondPattern = patterns[1] as? CodeBlock + { + let letIdentifier = IdentifierPatternSyntax(identifier: .identifier(firstPattern.name)) + let whereExpr = ExprSyntax( + fromProtocol: secondPattern.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + + let valueBindingPattern = ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: letIdentifier + ) + + let whereClause = WhereClauseSyntax( + whereKeyword: .keyword(.where, leadingTrivia: .space, trailingTrivia: .space), + condition: whereExpr + ) + + // Create a case item with the value binding pattern and where clause + let caseItem = SwitchCaseItemSyntax( + pattern: PatternSyntax(valueBindingPattern), + whereClause: whereClause + ) + finalCaseItems = SwitchCaseItemListSyntax([caseItem]) + } + } + + var statementItems = body.compactMap { block -> CodeBlockItemSyntax? in + if let decl = block.syntax.as(DeclSyntax.self) { + return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) + } else if let expr = block.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)).with(\.trailingTrivia, .newline) + } else if let stmt = block.syntax.as(StmtSyntax.self) { + return CodeBlockItemSyntax(item: .stmt(stmt)).with(\.trailingTrivia, .newline) + } + return nil + } + if statementItems.isEmpty { + // Add a break statement if the case body is empty + let breakStmt = BreakStmtSyntax(breakKeyword: .keyword(.break, trailingTrivia: .newline)) + statementItems = [CodeBlockItemSyntax(item: .stmt(StmtSyntax(breakStmt)))] + } + let statements = CodeBlockItemListSyntax(statementItems) let label = SwitchCaseLabelSyntax( caseKeyword: .keyword(.case, trailingTrivia: .space), - caseItems: caseItems, + caseItems: finalCaseItems, colon: .colonToken(trailingTrivia: .newline) ) return SwitchCaseSyntax( diff --git a/Sources/SyntaxKit/SwitchLet.swift b/Sources/SyntaxKit/SwitchLet.swift new file mode 100644 index 0000000..617fa22 --- /dev/null +++ b/Sources/SyntaxKit/SwitchLet.swift @@ -0,0 +1,55 @@ +// +// SwitchLet.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A value binding pattern for use in switch cases. +public struct SwitchLet: PatternConvertible, CodeBlock { + internal let name: String + + /// Creates a value binding pattern for a switch case. + /// - Parameter name: The name of the variable to bind. + public init(_ name: String) { + self.name = name + } + + public var patternSyntax: PatternSyntax { + let identifier = IdentifierPatternSyntax(identifier: .identifier(name)) + return PatternSyntax( + ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: identifier + )) + } + + public var syntax: SyntaxProtocol { + // For CodeBlock conformance, return the pattern syntax + patternSyntax + } +} diff --git a/Sources/SyntaxKit/Then.swift b/Sources/SyntaxKit/Then.swift new file mode 100644 index 0000000..dd2fc2e --- /dev/null +++ b/Sources/SyntaxKit/Then.swift @@ -0,0 +1,73 @@ +// +// Then.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A helper that represents the *final* `else` body in an `if` / `else-if` chain. +/// +/// In the DSL this lets users write: +/// ```swift +/// If { condition } then: { ... } else: { +/// If { otherCond } then: { ... } +/// Then { // <- final else +/// Call("print", "fallback") +/// } +/// } +/// ``` +/// so that the builder can distinguish a nested `If` (for `else if`) from the +/// *terminal* `else` body. +public struct Then: CodeBlock { + /// The statements that make up the `else` body. + public let body: [CodeBlock] + + public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.body = content() + } + + public var syntax: SyntaxProtocol { + let statements = CodeBlockItemListSyntax( + body.compactMap { element in + if let decl = element.syntax.as(DeclSyntax.self) { + return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) + } else if let expr = element.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)).with(\.trailingTrivia, .newline) + } else if let stmt = element.syntax.as(StmtSyntax.self) { + return CodeBlockItemSyntax(item: .stmt(stmt)).with(\.trailingTrivia, .newline) + } + return nil + } + ) + + return CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: statements, + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + } +} diff --git a/Sources/SyntaxKit/Tuple.swift b/Sources/SyntaxKit/Tuple.swift index 6179f7c..03bab7f 100644 --- a/Sources/SyntaxKit/Tuple.swift +++ b/Sources/SyntaxKit/Tuple.swift @@ -41,6 +41,18 @@ public struct Tuple: CodeBlock { self.elements = content() } + /// Creates a tuple pattern for switch cases. + /// - Parameter elements: Array of pattern elements, where `nil` represents a wildcard pattern. + public static func pattern(_ elements: [PatternConvertible?]) -> TuplePattern { + TuplePattern(elements: elements) + } + + /// Creates a tuple pattern that can be used as a CodeBlock. + /// - Parameter elements: Array of pattern elements, where `nil` represents a wildcard pattern. + public static func patternCodeBlock(_ elements: [PatternConvertible?]) -> TuplePatternCodeBlock { + TuplePatternCodeBlock(elements: elements) + } + public var syntax: SyntaxProtocol { guard !elements.isEmpty else { fatalError("Tuple must contain at least one element.") diff --git a/Sources/SyntaxKit/TupleLiteral.swift b/Sources/SyntaxKit/TupleLiteral.swift new file mode 100644 index 0000000..58b8fc4 --- /dev/null +++ b/Sources/SyntaxKit/TupleLiteral.swift @@ -0,0 +1,91 @@ +// +// TupleLiteral.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// A tuple value that can be used as a literal. +public struct TupleLiteral: LiteralValue { + let elements: [Literal?] + + /// Creates a tuple with the given elements. + /// - Parameter elements: The tuple elements, where `nil` represents a wildcard. + public init(_ elements: [Literal?]) { + self.elements = elements + } + + /// The Swift type name for this tuple. + public var typeName: String { + let elementTypes = elements.map { element in + if let element = element { + switch element { + case .integer: return "Int" + case .float: return "Double" + case .string: return "String" + case .boolean: return "Bool" + case .nil: return "Any?" + case .ref: return "Any" + case .tuple: return "Any" + case .array: return "Any" + case .dictionary: return "Any" + } + } else { + return "Any" + } + } + return "(\(elementTypes.joined(separator: ", ")))" + } + + /// Renders this tuple as a Swift literal string. + public var literalString: String { + let elementStrings = elements.map { element in + if let element = element { + switch element { + case .integer(let value): return String(value) + case .float(let value): return String(value) + case .string(let value): return "\"\(value)\"" + case .boolean(let value): return value ? "true" : "false" + case .nil: return "nil" + case .ref(let value): return value + case .tuple(let tupleElements): + let tuple = TupleLiteral(tupleElements) + return tuple.literalString + case .array(let arrayElements): + let array = ArrayLiteral(arrayElements) + return array.literalString + case .dictionary(let dictionaryElements): + let dictionary = DictionaryLiteral(dictionaryElements) + return dictionary.literalString + } + } else { + return "_" + } + } + return "(\(elementStrings.joined(separator: ", ")))" + } +} diff --git a/Sources/SyntaxKit/TuplePattern.swift b/Sources/SyntaxKit/TuplePattern.swift new file mode 100644 index 0000000..f739aea --- /dev/null +++ b/Sources/SyntaxKit/TuplePattern.swift @@ -0,0 +1,72 @@ +// +// TuplePattern.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A tuple pattern for switch cases. +public struct TuplePattern: PatternConvertible { + private let elements: [PatternConvertible?] + + internal init(elements: [PatternConvertible?]) { + self.elements = elements + } + + public var patternSyntax: PatternSyntax { + let patternElements = TuplePatternElementListSyntax( + elements.enumerated().map { index, element in + let patternElement: TuplePatternElementSyntax + if let element = element { + patternElement = TuplePatternElementSyntax( + label: nil, + colon: nil, + pattern: element.patternSyntax, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } else { + // Wildcard pattern + patternElement = TuplePatternElementSyntax( + label: nil, + colon: nil, + pattern: PatternSyntax(WildcardPatternSyntax(wildcard: .wildcardToken())), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + return patternElement + } + ) + + return PatternSyntax( + TuplePatternSyntax( + leftParen: .leftParenToken(), + elements: patternElements, + rightParen: .rightParenToken() + ) + ) + } +} diff --git a/Sources/SyntaxKit/TuplePatternCodeBlock.swift b/Sources/SyntaxKit/TuplePatternCodeBlock.swift new file mode 100644 index 0000000..f5436d2 --- /dev/null +++ b/Sources/SyntaxKit/TuplePatternCodeBlock.swift @@ -0,0 +1,78 @@ +// +// TuplePatternCodeBlock.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A tuple pattern that can be used as a CodeBlock for for-in loops. +public struct TuplePatternCodeBlock: CodeBlock, PatternConvertible { + private let elements: [PatternConvertible?] + + internal init(elements: [PatternConvertible?]) { + self.elements = elements + } + + public var patternSyntax: PatternSyntax { + let patternElements = TuplePatternElementListSyntax( + elements.enumerated().map { index, element in + let patternElement: TuplePatternElementSyntax + if let element = element { + patternElement = TuplePatternElementSyntax( + label: nil, + colon: nil, + pattern: element.patternSyntax, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } else { + // Wildcard pattern + patternElement = TuplePatternElementSyntax( + label: nil, + colon: nil, + pattern: PatternSyntax(WildcardPatternSyntax(wildcard: .wildcardToken())), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + return patternElement + } + ) + + return PatternSyntax( + TuplePatternSyntax( + leftParen: .leftParenToken(), + elements: patternElements, + rightParen: .rightParenToken() + ) + ) + } + + public var syntax: SyntaxProtocol { + // For CodeBlock conformance, we return the pattern syntax as an expression + // This is a bit of a hack, but it allows us to use TuplePatternCodeBlock in For loops + patternSyntax + } +} diff --git a/Sources/SyntaxKit/Variable+Initializers.swift b/Sources/SyntaxKit/Variable+Initializers.swift new file mode 100644 index 0000000..0799395 --- /dev/null +++ b/Sources/SyntaxKit/Variable+Initializers.swift @@ -0,0 +1,275 @@ +// +// Variable+Initializers.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +// MARK: - Variable Initializers + +extension Variable { + /// Creates a `let` or `var` declaration with an explicit type. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: The initial value expression of the variable, if any. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals defaultValue: CodeBlock? = nil, + explicitType: Bool? = nil + ) { + let finalExplicitType = explicitType ?? (defaultValue == nil) + self.init( + kind: kind, + name: name, + type: type, + defaultValue: defaultValue, + explicitType: finalExplicitType + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and string literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: A string literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: String, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.string(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and integer literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: An integer literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: Int, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.integer(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and boolean literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: A boolean literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: Bool, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.boolean(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and double literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: A double literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: Double, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.float(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with a literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: A literal value that conforms to ``LiteralValue``. + public init( + _ kind: VariableKind, name: String, equals value: T + ) { + let defaultValue: CodeBlock + if let literal = value as? Literal { + defaultValue = literal + } else if let tuple = value as? TupleLiteral { + defaultValue = Literal.tuple(tuple.elements) + } else if let array = value as? ArrayLiteral { + defaultValue = Literal.array(array.elements) + } else if let dict = value as? DictionaryLiteral { + defaultValue = Literal.dictionary(dict.elements) + } else if let array = value as? [String] { + defaultValue = Literal.array(array.map { .string($0) }) + } else if let dict = value as? [Int: String] { + defaultValue = Literal.dictionary(dict.map { (.integer($0.key), .string($0.value)) }) + } else { + fatalError("Variable: Only Literal types are supported for defaultValue. Got: \(T.self)") + } + + self.init( + kind: kind, + name: name, + type: value.typeName, + defaultValue: defaultValue, + explicitType: false + ) + } + + /// Creates a `let` or `var` declaration with a string literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: A string literal value. + public init( + _ kind: VariableKind, name: String, equals value: String + ) { + self.init( + kind: kind, + name: name, + type: "String", + defaultValue: Literal.string(value), + explicitType: false + ) + } + + /// Creates a `let` or `var` declaration with an integer literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: An integer literal value. + public init( + _ kind: VariableKind, name: String, equals value: Int + ) { + self.init( + kind: kind, + name: name, + type: "Int", + defaultValue: Literal.integer(value), + explicitType: false + ) + } + + /// Creates a `let` or `var` declaration with a boolean literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: A boolean literal value. + public init( + _ kind: VariableKind, name: String, equals value: Bool + ) { + self.init( + kind: kind, + name: name, + type: "Bool", + defaultValue: Literal.boolean(value), + explicitType: false + ) + } + + /// Creates a `let` or `var` declaration with a double literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: A double literal value. + public init( + _ kind: VariableKind, name: String, equals value: Double + ) { + self.init( + kind: kind, + name: name, + type: "Double", + defaultValue: Literal.float(value), + explicitType: false + ) + } + + /// Creates a `let` or `var` declaration with a Literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: A Literal value. + public init( + _ kind: VariableKind, name: String, equals value: Literal + ) { + self.init( + kind: kind, + name: name, + type: value.typeName, + defaultValue: value, + explicitType: false + ) + } + + /// Creates a `let` or `var` declaration with a value built from a CodeBlock builder closure. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - value: A builder closure that returns a CodeBlock for the initial value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, + name: String, + @CodeBlockBuilderResult value: () -> [CodeBlock], + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: "", + defaultValue: value().first ?? EmptyCodeBlock(), + explicitType: explicitType ?? false + ) + } +} diff --git a/Sources/SyntaxKit/Variable.swift b/Sources/SyntaxKit/Variable.swift index cf3f044..310b6c2 100644 --- a/Sources/SyntaxKit/Variable.swift +++ b/Sources/SyntaxKit/Variable.swift @@ -27,41 +27,38 @@ // OTHER DEALINGS IN THE SOFTWARE. // +import Foundation import SwiftSyntax /// A Swift `let` or `var` declaration with an explicit type. public struct Variable: CodeBlock { - private let kind: VariableKind - private let name: String - private let type: String - private let defaultValue: String? - private var isStatic: Bool = false - private var attributes: [AttributeInfo] = [] - - /// Creates a `let` or `var` declaration with an explicit type. + let kind: VariableKind + let name: String + let type: String + let defaultValue: CodeBlock? + var isStatic: Bool = false + var attributes: [AttributeInfo] = [] + var explicitType: Bool = false + + /// Internal initializer used by extension initializers to reduce code duplication. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable. - /// - defaultValue: The initial value of the variable, if any. - public init(_ kind: VariableKind, name: String, type: String, equals defaultValue: String? = nil) - { + /// - defaultValue: The initial value expression of the variable, if any. + /// - explicitType: Whether the variable has an explicit type. + internal init( + kind: VariableKind, + name: String, + type: String, + defaultValue: CodeBlock? = nil, + explicitType: Bool = false + ) { self.kind = kind self.name = name self.type = type self.defaultValue = defaultValue - } - - /// Creates a `let` or `var` declaration with a literal value. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - value: A literal value that conforms to ``LiteralValue``. - public init(_ kind: VariableKind, name: String, equals value: T) { - self.kind = kind - self.name = name - self.type = value.typeName - self.defaultValue = value.literalString + self.explicitType = explicitType } /// Marks the variable as `static`. @@ -83,28 +80,41 @@ public struct Variable: CodeBlock { return copy } + public func withExplicitType() -> Self { + var copy = self + copy.explicitType = true + return copy + } + public var syntax: SyntaxProtocol { let bindingKeyword = TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) - let typeAnnotation = TypeAnnotationSyntax( - colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(type)) - ) - + let typeAnnotation: TypeAnnotationSyntax? = + (explicitType && !type.isEmpty) + ? TypeAnnotationSyntax( + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(type)) + ) : nil let initializer = defaultValue.map { value in - InitializerClauseSyntax( + let expr: ExprSyntax + if let exprBlock = value as? ExprCodeBlock { + expr = exprBlock.exprSyntax + } else if let exprSyntax = value.syntax.as(ExprSyntax.self) { + expr = exprSyntax + } else { + expr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } + return InitializerClauseSyntax( equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) + value: expr ) } - var modifiers: DeclModifierListSyntax = [] if isStatic { modifiers = DeclModifierListSyntax([ DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) ]) } - return VariableDeclSyntax( attributes: buildAttributeList(from: attributes), modifiers: modifiers, diff --git a/Sources/SyntaxKit/VariableDecl.swift b/Sources/SyntaxKit/VariableDecl.swift index 64da71b..27f1029 100644 --- a/Sources/SyntaxKit/VariableDecl.swift +++ b/Sources/SyntaxKit/VariableDecl.swift @@ -50,7 +50,7 @@ public struct VariableDecl: CodeBlock { let bindingKeyword = TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) let initializer = value.map { value in - if value.hasPrefix("\"") && value.hasSuffix("\"") || value.contains("\\(") { + if value.hasPrefix("\"") && value.hasSuffix("\"") { return InitializerClauseSyntax( equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), value: StringLiteralExprSyntax( @@ -62,6 +62,18 @@ public struct VariableDecl: CodeBlock { closingQuote: .stringQuoteToken() ) ) + } else if value.contains("\\(") { + return InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: StringLiteralExprSyntax( + openingQuote: .stringQuoteToken(), + segments: StringLiteralSegmentListSyntax([ + .stringSegment( + StringSegmentSyntax(content: .stringSegment(value))) + ]), + closingQuote: .stringQuoteToken() + ) + ) } else { return InitializerClauseSyntax( equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), diff --git a/Sources/SyntaxKit/VariableExp.swift b/Sources/SyntaxKit/VariableExp.swift index fb55e86..f35234a 100644 --- a/Sources/SyntaxKit/VariableExp.swift +++ b/Sources/SyntaxKit/VariableExp.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// An expression that refers to a variable. -public struct VariableExp: CodeBlock { +public struct VariableExp: CodeBlock, PatternConvertible { internal let name: String /// Creates a variable expression. @@ -65,7 +65,11 @@ public struct VariableExp: CodeBlock { } public var syntax: SyntaxProtocol { - TokenSyntax.identifier(name) + ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) + } + + public var patternSyntax: PatternSyntax { + PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(name))) } } diff --git a/Sources/SyntaxKit/While.swift b/Sources/SyntaxKit/While.swift new file mode 100644 index 0000000..1d2aafc --- /dev/null +++ b/Sources/SyntaxKit/While.swift @@ -0,0 +1,99 @@ +// +// While.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A `while` loop statement. +public struct While: CodeBlock { + private let condition: CodeBlock + private let body: [CodeBlock] + + /// Creates a `while` loop statement. + /// - Parameters: + /// - condition: A `CodeBlockBuilder` that produces the condition expression. + /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. + public init( + @CodeBlockBuilderResult _ condition: () -> [CodeBlock], + @CodeBlockBuilderResult then: () -> [CodeBlock] + ) { + let conditions = condition() + guard conditions.count == 1 else { + fatalError("While requires exactly one condition CodeBlock") + } + self.condition = conditions[0] + self.body = then() + } + + /// Convenience initializer that accepts a single condition directly. + /// - Parameters: + /// - condition: The condition expression. + /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. + public init( + _ condition: CodeBlock, + @CodeBlockBuilderResult then: () -> [CodeBlock] + ) { + self.init({ condition }, then: then) + } + + public var syntax: SyntaxProtocol { + let conditionExpr = ExprSyntax( + fromProtocol: condition.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + + let bodyBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax( + body.compactMap { + var item: CodeBlockItemSyntax? + if let decl = $0.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = $0.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = $0.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + }), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + return StmtSyntax( + WhileStmtSyntax( + whileKeyword: .keyword(.while, trailingTrivia: .space), + conditions: ConditionElementListSyntax([ + ConditionElementSyntax( + condition: .expression(conditionExpr) + ) + ]), + body: bodyBlock + ) + ) + } +} diff --git a/Sources/SyntaxKit/parser/SourceRange.swift b/Sources/SyntaxKit/parser/SourceRange.swift new file mode 100644 index 0000000..c29b2ce --- /dev/null +++ b/Sources/SyntaxKit/parser/SourceRange.swift @@ -0,0 +1,50 @@ +// +// SourceRange.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +internal struct SourceRange: Codable, Equatable { + internal let startRow: Int + internal let startColumn: Int + internal let endRow: Int + internal let endColumn: Int +} + +extension SourceRange: CustomStringConvertible { + var description: String { + """ + { + startRow: \(startRow) + startColumn: \(startColumn) + endRow: \(endRow) + endColumn: \(endColumn) + } + """ + } +} diff --git a/Sources/SyntaxKit/parser/String+Extensions.swift b/Sources/SyntaxKit/parser/String+Extensions.swift new file mode 100644 index 0000000..861317a --- /dev/null +++ b/Sources/SyntaxKit/parser/String+Extensions.swift @@ -0,0 +1,38 @@ +// +// String+Extensions.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +extension String { + internal func replaceHTMLWhitespacesToSymbols() -> String { + self + .replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "
", with: "") + } +} diff --git a/Sources/SyntaxKit/parser/StructureProperty.swift b/Sources/SyntaxKit/parser/StructureProperty.swift new file mode 100644 index 0000000..5c5f72e --- /dev/null +++ b/Sources/SyntaxKit/parser/StructureProperty.swift @@ -0,0 +1,54 @@ +// +// StructureProperty.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +internal struct StructureProperty: Codable, Equatable { + internal let name: String + internal let value: StructureValue? + internal let ref: String? + + init(name: String, value: StructureValue? = nil, ref: String? = nil) { + self.name = name.escapeHTML() + self.value = value + self.ref = ref?.escapeHTML() + } +} + +extension StructureProperty: CustomStringConvertible { + var description: String { + """ + { + name: \(name) + value: \(String(describing: value)) + ref: \(String(describing: ref)) + } + """ + } +} diff --git a/Sources/SyntaxKit/parser/StructureValue.swift b/Sources/SyntaxKit/parser/StructureValue.swift new file mode 100644 index 0000000..63aa525 --- /dev/null +++ b/Sources/SyntaxKit/parser/StructureValue.swift @@ -0,0 +1,51 @@ +// +// StructureValue.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +internal struct StructureValue: Codable, Equatable { + internal let text: String + internal let kind: String? + + init(text: String, kind: String? = nil) { + self.text = text.escapeHTML().replaceHTMLWhitespacesToSymbols() + self.kind = kind?.escapeHTML() + } +} + +extension StructureValue: CustomStringConvertible { + var description: String { + """ + { + text: \(text) + kind: \(String(describing: kind)) + } + """ + } +} diff --git a/Sources/SyntaxKit/parser/SyntaxParser.swift b/Sources/SyntaxKit/parser/SyntaxParser.swift index f4f38e5..65b0ef7 100644 --- a/Sources/SyntaxKit/parser/SyntaxParser.swift +++ b/Sources/SyntaxKit/parser/SyntaxParser.swift @@ -51,7 +51,8 @@ package enum SyntaxParser { let tree = visitor.tree let encoder = JSONEncoder() - let json = String(decoding: try encoder.encode(tree), as: UTF8.self) + let data = try encoder.encode(tree) + let json = String(decoding: data, as: UTF8.self) return SyntaxResponse(syntaxJSON: json) } diff --git a/Sources/SyntaxKit/parser/SyntaxType.swift b/Sources/SyntaxKit/parser/SyntaxType.swift new file mode 100644 index 0000000..716b27d --- /dev/null +++ b/Sources/SyntaxKit/parser/SyntaxType.swift @@ -0,0 +1,39 @@ +// +// SyntaxType.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +internal enum SyntaxType: String, Codable { + case decl + case expr + case pattern + case type + case collection + case other +} diff --git a/Sources/SyntaxKit/parser/Token.swift b/Sources/SyntaxKit/parser/Token.swift new file mode 100644 index 0000000..48c0729 --- /dev/null +++ b/Sources/SyntaxKit/parser/Token.swift @@ -0,0 +1,54 @@ +// +// Token.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +internal struct Token: Codable, Equatable { + internal let kind: String + internal var leadingTrivia: String + internal var trailingTrivia: String + + init(kind: String, leadingTrivia: String, trailingTrivia: String) { + self.kind = kind.escapeHTML() + self.leadingTrivia = leadingTrivia + self.trailingTrivia = trailingTrivia + } +} + +extension Token: CustomStringConvertible { + var description: String { + """ + { + kind: \(kind) + leadingTrivia: \(leadingTrivia) + trailingTrivia: \(trailingTrivia) + } + """ + } +} diff --git a/Sources/SyntaxKit/parser/TokenVisitor.swift b/Sources/SyntaxKit/parser/TokenVisitor.swift index f377831..4eef1ff 100644 --- a/Sources/SyntaxKit/parser/TokenVisitor.swift +++ b/Sources/SyntaxKit/parser/TokenVisitor.swift @@ -94,7 +94,7 @@ internal final class TokenVisitor: SyntaxRewriter { let treeNode = TreeNode( id: index, text: className, - range: Range( + range: SourceRange( startRow: start.line, startColumn: start.column, endRow: end.line, @@ -186,12 +186,12 @@ internal final class TokenVisitor: SyntaxRewriter { current.token = Token(kind: "\(token.tokenKind)", leadingTrivia: "", trailingTrivia: "") - token.leadingTrivia.forEach { piece in + for piece in token.leadingTrivia { let trivia = processTriviaPiece(piece) current.token?.leadingTrivia += trivia.replaceHTMLWhitespacesWithSymbols() } processToken(token) - token.trailingTrivia.forEach { piece in + for piece in token.trailingTrivia { let trivia = processTriviaPiece(piece) current.token?.trailingTrivia += trivia.replaceHTMLWhitespacesWithSymbols() } diff --git a/Sources/SyntaxKit/parser/TreeNode.swift b/Sources/SyntaxKit/parser/TreeNode.swift index a83ec0d..a649c78 100644 --- a/Sources/SyntaxKit/parser/TreeNode.swift +++ b/Sources/SyntaxKit/parser/TreeNode.swift @@ -34,13 +34,13 @@ internal final class TreeNode: Codable { internal var parent: Int? internal var text: String - internal var range = Range( + internal var range = SourceRange( startRow: 0, startColumn: 0, endRow: 0, endColumn: 0) internal var structure = [StructureProperty]() internal var type: SyntaxType internal var token: Token? - init(id: Int, text: String, range: Range, type: SyntaxType) { + init(id: Int, text: String, range: SourceRange, type: SyntaxType) { self.id = id self.text = text.escapeHTML() self.range = range @@ -70,109 +70,3 @@ extension TreeNode: CustomStringConvertible { """ } } - -internal struct Range: Codable, Equatable { - internal let startRow: Int - internal let startColumn: Int - internal let endRow: Int - internal let endColumn: Int -} - -extension Range: CustomStringConvertible { - var description: String { - """ - { - startRow: \(startRow) - startColumn: \(startColumn) - endRow: \(endRow) - endColumn: \(endColumn) - } - """ - } -} - -internal struct StructureProperty: Codable, Equatable { - internal let name: String - internal let value: StructureValue? - internal let ref: String? - - init(name: String, value: StructureValue? = nil, ref: String? = nil) { - self.name = name.escapeHTML() - self.value = value - self.ref = ref?.escapeHTML() - } -} - -extension StructureProperty: CustomStringConvertible { - var description: String { - """ - { - name: \(name) - value: \(String(describing: value)) - ref: \(String(describing: ref)) - } - """ - } -} - -internal struct StructureValue: Codable, Equatable { - internal let text: String - internal let kind: String? - - init(text: String, kind: String? = nil) { - self.text = text.escapeHTML().replaceHTMLWhitespacesToSymbols() - self.kind = kind?.escapeHTML() - } -} - -extension StructureValue: CustomStringConvertible { - var description: String { - """ - { - text: \(text) - kind: \(String(describing: kind)) - } - """ - } -} - -internal enum SyntaxType: String, Codable { - case decl - case expr - case pattern - case type - case collection - case other -} - -internal struct Token: Codable, Equatable { - internal let kind: String - internal var leadingTrivia: String - internal var trailingTrivia: String - - init(kind: String, leadingTrivia: String, trailingTrivia: String) { - self.kind = kind.escapeHTML() - self.leadingTrivia = leadingTrivia - self.trailingTrivia = trailingTrivia - } -} - -extension Token: CustomStringConvertible { - var description: String { - """ - { - kind: \(kind) - leadingTrivia: \(leadingTrivia) - trailingTrivia: \(trailingTrivia) - } - """ - } -} - -extension String { - fileprivate func replaceHTMLWhitespacesToSymbols() -> String { - self - .replacingOccurrences(of: " ", with: "") - .replacingOccurrences(of: "
", with: "") - } -} diff --git a/Tests/SyntaxKitTests/Integration/.swiftlint.yml b/Tests/SyntaxKitTests/Integration/.swiftlint.yml new file mode 100644 index 0000000..a3bbf04 --- /dev/null +++ b/Tests/SyntaxKitTests/Integration/.swiftlint.yml @@ -0,0 +1,5 @@ +disabled_rules: + - file_length + - closure_body_length + - function_body_length + - type_body_length \ No newline at end of file diff --git a/Tests/SyntaxKitTests/BasicTests.swift b/Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift similarity index 77% rename from Tests/SyntaxKitTests/BasicTests.swift rename to Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift index 2fb77b3..b44ed10 100644 --- a/Tests/SyntaxKitTests/BasicTests.swift +++ b/Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift @@ -2,7 +2,8 @@ import Testing @testable import SyntaxKit -internal struct BasicTests { +@Suite +internal struct BlackjackCardTests { @Test internal func testBlackjackCardExample() throws { let blackjackCard = Struct("BlackjackCard") { Enum("Suit") { @@ -15,12 +16,12 @@ internal struct BasicTests { let expected = """ struct BlackjackCard { - enum Suit: Character { - case spades = "♠" - case hearts = "♡" - case diamonds = "♢" - case clubs = "♣" - } + enum Suit: Character { + case spades = "♠" + case hearts = "♡" + case diamonds = "♢" + case clubs = "♣" + } } """ diff --git a/Tests/SyntaxKitTests/BlackjackTests.swift b/Tests/SyntaxKitTests/Integration/BlackjackTests.swift similarity index 72% rename from Tests/SyntaxKitTests/BlackjackTests.swift rename to Tests/SyntaxKitTests/Integration/BlackjackTests.swift index 0d71ceb..ee51ff2 100644 --- a/Tests/SyntaxKitTests/BlackjackTests.swift +++ b/Tests/SyntaxKitTests/Integration/BlackjackTests.swift @@ -36,29 +36,29 @@ internal struct BlackjackTests { let expected = """ struct BlackjackCard { - enum Suit: Character { - case spades = "♠" - case hearts = "♡" - case diamonds = "♢" - case clubs = "♣" - } - enum Rank: Int { - case two = 2 - case three - case four - case five - case six - case seven - case eight - case nine - case ten - case jack - case queen - case king - case ace - } - let rank: Rank - let suit: Suit + enum Suit: Character { + case spades = "♠" + case hearts = "♡" + case diamonds = "♢" + case clubs = "♣" + } + enum Rank: Int { + case two = 2 + case three + case four + case five + case six + case seven + case eight + case nine + case ten + case jack + case queen + case king + case ace + } + let rank: Rank + let suit: Suit } """ @@ -70,9 +70,7 @@ internal struct BlackjackTests { #expect(normalizedGenerated == normalizedExpected) } - // swiftlint:disable:next function_body_length @Test internal func testFullBlackjackCardExample() throws { - // swiftlint:disable:next closure_body_length let syntax = Struct("BlackjackCard") { Enum("Suit") { EnumCase("spades").equals("♠") @@ -105,24 +103,24 @@ internal struct BlackjackTests { SwitchCase(".ace") { Return { Init("Values") { - Parameter(name: "first", type: "", defaultValue: "1") - Parameter(name: "second", type: "", defaultValue: "11") + ParameterExp(name: "first", value: Literal.integer(1)) + ParameterExp(name: "second", value: Literal.integer(11)) } } } SwitchCase(".jack", ".queen", ".king") { Return { Init("Values") { - Parameter(name: "first", type: "", defaultValue: "10") - Parameter(name: "second", type: "", defaultValue: "nil") + ParameterExp(name: "first", value: Literal.integer(10)) + ParameterExp(name: "second", value: Literal.nil) } } } Default { Return { Init("Values") { - Parameter(name: "first", type: "", defaultValue: "self.rawValue") - Parameter(name: "second", type: "", defaultValue: "nil") + ParameterExp(name: "first", value: Literal.ref("self.rawValue")) + ParameterExp(name: "second", value: Literal.nil) } } } @@ -134,12 +132,12 @@ internal struct BlackjackTests { Variable(.let, name: "rank", type: "Rank") Variable(.let, name: "suit", type: "Suit") ComputedProperty("description", type: "String") { - VariableDecl(.var, name: "output", equals: "\"suit is \\(suit.rawValue),\"") - PlusAssign("output", "\" value is \\(rank.values.first)\"") + VariableDecl(.var, name: "output", equals: "suit is \\(suit.rawValue),") + PlusAssign("output", " value is \\(rank.values.first)") If( Let("second", "rank.values.second"), then: { - PlusAssign("output", "\" or \\(second)\"") + PlusAssign("output", " or \\(second)") } ) Return { @@ -151,10 +149,10 @@ internal struct BlackjackTests { let expected = """ struct BlackjackCard { enum Suit: Character { - case spades = \"♠\" - case hearts = \"♡\" - case diamonds = \"♢\" - case clubs = \"♣\" + case spades = "♠" + case hearts = "♡" + case diamonds = "♢" + case clubs = "♣" } enum Rank: Int { @@ -192,10 +190,10 @@ internal struct BlackjackTests { let rank: Rank let suit: Suit var description: String { - var output = \"suit is \\(suit.rawValue),\" - output += \" value is \\(rank.values.first)\" + var output = "suit is \\(suit.rawValue)," + output += " value is \\(rank.values.first)" if let second = rank.values.second { - output += \" or \\(second)\" + output += " or \\(second)" } return output } diff --git a/Tests/SyntaxKitTests/CommentTests.swift b/Tests/SyntaxKitTests/Integration/CommentTests.swift similarity index 97% rename from Tests/SyntaxKitTests/CommentTests.swift rename to Tests/SyntaxKitTests/Integration/CommentTests.swift index e56fdcd..1cd2e8e 100644 --- a/Tests/SyntaxKitTests/CommentTests.swift +++ b/Tests/SyntaxKitTests/Integration/CommentTests.swift @@ -3,9 +3,7 @@ import Testing @testable import SyntaxKit internal struct CommentTests { - // swiftlint:disable:next function_body_length @Test internal func testCommentInjection() { - // swiftlint:disable:next closure_body_length let syntax = Group { Struct("Card") { Variable(.let, name: "rank", type: "Rank") diff --git a/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift b/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift new file mode 100644 index 0000000..a28ff50 --- /dev/null +++ b/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift @@ -0,0 +1,297 @@ +// +// CompleteProtocolsExampleTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SyntaxKit +import Testing + +@Suite internal struct CompleteProtocolsExampleTests { + // MARK: - Helper Functions + + private func createProtocolsDSL() -> Group { + Group { + // MARK: - Protocol Definition + Protocol("Vehicle") { + PropertyRequirement("numberOfWheels", type: "Int", access: .get) + PropertyRequirement("brand", type: "String", access: .get) + FunctionRequirement("start") + FunctionRequirement("stop") + } + .comment { + Line("MARK: - Protocol Definition") + } + + // MARK: - Protocol Extension + Extension("Vehicle") { + Function("start") { + Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) vehicle...\"") + } + } + + Function("stop") { + Call("print") { + ParameterExp(name: "", value: "\"Stopping \\(brand) vehicle...\"") + } + } + } + .comment { + Line("MARK: - Protocol Extension") + } + + // MARK: - Protocol Composition + Protocol("Electric") { + PropertyRequirement("batteryLevel", type: "Double", access: .getSet) + FunctionRequirement("charge") + } + .comment { + Line("MARK: - Protocol Composition") + } + + // MARK: - Concrete Types + Struct("Car") { + Variable(.let, name: "numberOfWheels", type: "Int", equals: 4).withExplicitType() + Variable(.let, name: "brand", type: "String").withExplicitType() + + Function("start") { + Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) car engine...\"") + } + } + } + .inherits("Vehicle") + .comment { + Line("MARK: - Concrete Types") + } + + Struct("ElectricCar") { + Variable(.let, name: "numberOfWheels", type: "Int", equals: 4).withExplicitType() + Variable(.let, name: "brand", type: "String").withExplicitType() + Variable(.var, name: "batteryLevel", type: "Double").withExplicitType() + + Function("charge") { + Call("print") { + ParameterExp(name: "", value: "\"Charging \\(brand) electric car...\"") + } + Assignment("batteryLevel", Literal.float(100.0)) + } + } + .inherits("Vehicle", "Electric") + + // MARK: - Usage Example + VariableDecl(.let, name: "tesla", equals: "ElectricCar(brand: \"Tesla\", batteryLevel: 75.0)") + .comment { + Line("MARK: - Usage Example") + } + VariableDecl(.let, name: "toyota", equals: "Car(brand: \"Toyota\")") + + // Demonstrate protocol usage + Function("demonstrateVehicle") { + Parameter(name: "vehicle", type: "Vehicle", isUnnamed: true) + } _: { + Call("print") { + ParameterExp(name: "", value: "\"Vehicle brand: \\(vehicle.brand)\"") + } + Call("print") { + ParameterExp(name: "", value: "\"Number of wheels: \\(vehicle.numberOfWheels)\"") + } + VariableExp("vehicle").call("start") + VariableExp("vehicle").call("stop") + } + .comment { + Line("Demonstrate protocol usage") + } + + // Demonstrate protocol composition + Function("demonstrateElectricVehicle") { + Parameter(name: "vehicle", type: "Vehicle & Electric", isUnnamed: true) + } _: { + Call("demonstrateVehicle") { + ParameterExp(name: "", value: "vehicle") + } + Call("print") { + ParameterExp(name: "", value: "\"Battery level: \\(vehicle.batteryLevel)%\"") + } + VariableExp("vehicle").call("charge") + } + .comment { + Line("Demonstrate protocol composition") + } + + // Test the implementations + Call("print") { + ParameterExp(name: "", value: "\"Testing regular car:\"") + } + .comment { + Line("Test the implementations") + } + Call("demonstrateVehicle") { + ParameterExp(name: "", value: "toyota") + } + + Call("print") { + ParameterExp(name: "", value: "\"Testing electric car:\"") + } + Call("demonstrateElectricVehicle") { + ParameterExp(name: "", value: "tesla") + } + } + } + + // MARK: - Tests + + @Test("Complete protocols example with Call generates correct syntax") + internal func testCompleteProtocolsExample() throws { + let generatedCode = createProtocolsDSL().generateCode() + + // Verify protocol definitions + #expect(generatedCode.contains("protocol Vehicle")) + #expect(generatedCode.contains("var numberOfWheels")) + #expect(generatedCode.contains("var brand")) + #expect(generatedCode.contains("func start()")) + #expect(generatedCode.contains("func stop()")) + + // Verify protocol extension + #expect(generatedCode.contains("extension Vehicle")) + #expect(generatedCode.contains("print(\"Starting \\(brand) vehicle...\")")) + #expect(generatedCode.contains("print(\"Stopping \\(brand) vehicle...\")")) + + // Verify protocol composition + #expect(generatedCode.contains("protocol Electric")) + #expect(generatedCode.contains("var batteryLevel")) + #expect(generatedCode.contains("func charge()")) + + // Verify concrete types + #expect(generatedCode.contains("struct Car:Vehicle")) + #expect(generatedCode.contains("struct ElectricCar:Vehicle")) + #expect(generatedCode.contains("print(\"Starting \\(brand) car engine...\")")) + #expect(generatedCode.contains("print(\"Charging \\(brand) electric car...\")")) + + // Verify usage examples + #expect(generatedCode.contains("let tesla")) + #expect(generatedCode.contains("let toyota")) + + // Verify demonstration functions + #expect(generatedCode.contains("func demonstrateVehicle")) + #expect(generatedCode.contains("func demonstrateElectricVehicle")) + #expect(generatedCode.contains("print(\"Vehicle brand: \\(vehicle.brand)\")")) + #expect(generatedCode.contains("print(\"Number of wheels: \\(vehicle.numberOfWheels)\")")) + #expect(generatedCode.contains("print(\"Battery level: \\(vehicle.batteryLevel)%\")")) + + // Verify test calls + #expect(generatedCode.contains("print(\"Testing regular car:\")")) + #expect(generatedCode.contains("print(\"Testing electric car:\")")) + } + + @Test("Protocols DSL and code.swift generate equivalent code") + internal func testProtocolsDSLAndCodeSwiftEquivalence() throws { + // Hardcoded code.swift content + let codeSwift = """ + // MARK: - Protocol Definition + protocol Vehicle { + var numberOfWheels: Int { get } + var brand: String { get } + func start() + func stop() + } + + // MARK: - Protocol Extension + extension Vehicle { + func start() { + print("Starting \\(brand) vehicle...") + } + + func stop() { + print("Stopping \\(brand) vehicle...") + } + } + + // MARK: - Protocol Composition + protocol Electric { + var batteryLevel: Double { get set } + func charge() + } + + // MARK: - Concrete Types + struct Car: Vehicle { + let numberOfWheels: Int = 4 + let brand: String + + func start() { + print("Starting \\(brand) car engine...") + } + } + + struct ElectricCar: Vehicle, Electric { + let numberOfWheels: Int = 4 + let brand: String + var batteryLevel: Double + + func charge() { + print("Charging \\(brand) electric car...") + batteryLevel = 100.0 + } + } + + // MARK: - Usage Example + let tesla = ElectricCar(brand: "Tesla", batteryLevel: 75.0) + let toyota = Car(brand: "Toyota") + + // Demonstrate protocol usage + func demonstrateVehicle(_ vehicle: Vehicle) { + print("Vehicle brand: \\(vehicle.brand)") + print("Number of wheels: \\(vehicle.numberOfWheels)") + vehicle.start() + vehicle.stop() + } + + // Demonstrate protocol composition + func demonstrateElectricVehicle(_ vehicle: Vehicle & Electric) { + demonstrateVehicle(vehicle) + print("Battery level: \\(vehicle.batteryLevel)%") + vehicle.charge() + } + + // Test the implementations + print("Testing regular car:") + demonstrateVehicle(toyota) + + print("Testing electric car:") + demonstrateElectricVehicle(tesla) + """ + + // Evaluate the DSL directly + let generatedCode = createProtocolsDSL().generateCode() + + // Normalize both + let normalizedCode = codeSwift.normalize() + let normalizedGenerated = generatedCode.normalize() + #expect(normalizedCode == normalizedGenerated) + } +} diff --git a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift new file mode 100644 index 0000000..585c458 --- /dev/null +++ b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift @@ -0,0 +1,486 @@ +import Foundation +import Testing + +@testable import SyntaxKit + +@Suite internal struct ConditionalsExampleTests { + @Test("Completed conditionals DSL generates expected Swift code") + internal func testCompletedConditionalsExample() throws { + // Build DSL equivalent of Examples/Completed/conditionals/dsl.swift + + let program = Group { + // MARK: Basic If Statements + Variable(.let, name: "temperature", equals: 25) + .comment { + Line("Simple if statement") + } + + If { + Infix(">") { + VariableExp("temperature") + Literal.integer(30) + } + } then: { + Call("print") { + ParameterExp(name: "", value: "\"It's hot outside!\"") + } + } + + // If-else chain with else-if + Variable(.let, name: "score", equals: 85) + .comment { + Line("If-else statement") + } + + If { + Infix(">=") { + VariableExp("score") + Literal.integer(90) + } + } then: { + Call("print") { + ParameterExp(name: "", value: "\"Excellent!\"") + } + } else: { + If { + Infix(">=") { + VariableExp("score") + Literal.integer(80) + } + } then: { + Call("print") { + ParameterExp(name: "", value: "\"Good job!\"") + } + } + + If { + Infix(">=") { + VariableExp("score") + Literal.integer(70) + } + } then: { + Call("print") { + ParameterExp(name: "", value: "\"Passing\"") + } + } + + Then { + Call("print") { + ParameterExp(name: "", value: "\"Needs improvement\"") + } + } + } + + // MARK: Optional Binding with If + Variable(.let, name: "possibleNumber", equals: Literal.string("123")) + .comment { + Line("MARK: - Optional Binding with If") + Line("Using if let for optional binding") + } + + If( + Let("actualNumber", "Int(possibleNumber)"), + then: { + Call("print") { + ParameterExp( + name: "", + value: + "\"The string \"\\(possibleNumber)\" has an integer value of \\(actualNumber)\"" + ) + } + }, + else: { + Call("print") { + ParameterExp( + name: "", + value: + "\"The string \"\\(possibleNumber)\" could not be converted to an integer\"" + ) + } + }) + + // Multiple optional bindings + Variable(.let, name: "possibleName", type: "String?", equals: Literal.string("John")) + .withExplicitType() + .comment { + Line("Multiple optional bindings") + } + Variable(.let, name: "possibleAge", type: "Int?", equals: Literal.integer(30)) + .withExplicitType() + + If { + Let("name", "possibleName") + Let("age", "possibleAge") + } then: { + Call("print") { + ParameterExp(name: "", value: "\"\\(name) is \\(age) years old\"") + } + } + + // MARK: - Guard Statements + Function("greet", { Parameter(name: "person", type: "[String: String]") }) { + Guard { + Let("name", "person[\"name\"]") + } else: { + Call("print") { + ParameterExp(name: "", value: "\"No name provided\"") + } + } + + Guard { + Let("age", "person[\"age\"]") + Let("ageInt", "Int(age)") + } else: { + Call("print") { + ParameterExp(name: "", value: "\"Invalid age provided\"") + } + } + + Call("print") { + ParameterExp(name: "", value: "\"Hello \\(name), you are \\(ageInt) years old\"") + } + } + .comment { + Line("MARK: - Guard Statements") + } + + // MARK: - Switch Statements + Variable(.let, name: "approximateCount", equals: Literal.integer(62)) + .comment { + Line("MARK: - Switch Statements") + Line("Switch with range matching") + } + Variable(.let, name: "countedThings", equals: Literal.string("moons orbiting Saturn")) + Variable(.let, name: "naturalCount", type: "String").withExplicitType() + Switch("approximateCount") { + SwitchCase(0) { + Assignment("naturalCount", Literal.string("no")) + } + SwitchCase(1..<5) { + Assignment("naturalCount", Literal.string("a few")) + } + SwitchCase(5..<12) { + Assignment("naturalCount", Literal.string("several")) + } + SwitchCase(12..<100) { + Assignment("naturalCount", Literal.string("dozens of")) + } + SwitchCase(100..<1_000) { + Assignment("naturalCount", Literal.string("hundreds of")) + } + Default { + Assignment("naturalCount", Literal.string("many")) + } + } + Call("print") { + ParameterExp(name: "", value: "\"There are \\(naturalCount) \\(countedThings).\"") + } + + // MARK: - Tuple literal and tuple pattern switch + Variable(.let, name: "somePoint", equals: Literal.tuple([.integer(1), .integer(1)])) + .comment { + Line("Switch with tuple matching") + } + Switch("somePoint") { + SwitchCase(Tuple.pattern([0, 0])) { + Call("print") { + ParameterExp(name: "", value: "\"(0, 0) is at the origin\"") + } + } + SwitchCase(Tuple.pattern([nil, 0])) { + Call("print") { + ParameterExp(name: "", value: "\"(\\(somePoint.0), 0) is on the x-axis\"") + } + } + SwitchCase(Tuple.pattern([0, nil])) { + Call("print") { + ParameterExp(name: "", value: "\"(0, \\(somePoint.1)) is on the y-axis\"") + } + } + SwitchCase(Tuple.pattern([(-2...2), (-2...2)])) { + Call("print") { + ParameterExp( + name: "", value: "\"(\\(somePoint.0), \\(somePoint.1)) is inside the box\"") + } + } + Default { + Call("print") { + ParameterExp( + name: "", value: "\"(\\(somePoint.0), \\(somePoint.1)) is outside of the box\"") + } + } + } + + // MARK: - Switch with value binding + Variable(.let, name: "anotherPoint", equals: Literal.tuple([.integer(2), .integer(0)])) + .withExplicitType() + .comment { + Line("Switch with value binding") + } + Switch("anotherPoint") { + SwitchCase(Tuple.pattern([Pattern.let("x"), 0])) { + Call("print") { + ParameterExp(name: "", value: "\"on the x-axis with an x value of \\(x)\"") + } + } + SwitchCase(Tuple.pattern([0, Pattern.let("y")])) { + Call("print") { + ParameterExp(name: "", value: "\"on the y-axis with a y value of \\(y)\"") + } + } + SwitchCase(Tuple.pattern([Pattern.let("x"), Pattern.let("y")])) { + Call("print") { + ParameterExp(name: "", value: "\"somewhere else at (\\(x), \\(y))\"") + } + } + } + + // MARK: - Fallthrough + Variable(.let, name: "integerToDescribe", equals: Literal.integer(5)) + .comment { + Line("MARK: - Fallthrough") + Line("Using fallthrough in switch") + } + Variable(.var, name: "description", equals: "The number \\(integerToDescribe) is") + Switch("integerToDescribe") { + SwitchCase(2, 3, 5, 7, 11, 13, 17, 19) { + PlusAssign("description", " a prime number, and also") + Fallthrough() + } + Default { + PlusAssign("description", " an integer.") + } + } + Call("print") { + ParameterExp(name: "", value: "description") + } + + // MARK: - Labeled Statements + Variable(.let, name: "finalSquare", equals: Literal.integer(25)) + .comment { + Line("MARK: - Labeled Statements") + Line("Using labeled statements with break") + } + Variable(.var, name: "board") { + Init("[Int]") { + ParameterExp(name: "repeating", value: Literal.integer(0)) + ParameterExp( + name: "count", + value: Infix("+") { + VariableExp("finalSquare") + Literal.integer(1) + }) + } + } + + // Board setup + Assignment("board[3]", 8) + Assignment("board[6]", 11) + Assignment("board[9]", 9) + Assignment("board[10]", 2) + Assignment("board[14]", -10) + Assignment("board[19]", -11) + Assignment("board[22]", -2) + Assignment("board[24]", -8) + + Variable(.var, name: "square", equals: Literal.integer(0)) + Variable(.var, name: "diceRoll", equals: Literal.integer(0)) + While { + Infix("!=") { + VariableExp("square") + VariableExp("finalSquare") + } + } then: { + PlusAssign("diceRoll", 1) + If { + Infix("==") { + VariableExp("diceRoll") + Literal.integer(7) + } + } then: { + Assignment("diceRoll", 1) + } + Switch( + Infix("+") { + VariableExp("square") + VariableExp("diceRoll") + } + ) { + SwitchCase(VariableExp("finalSquare")) { + Break() + } + SwitchCase { + SwitchLet("newSquare") + Infix(">") { + VariableExp("newSquare") + VariableExp("finalSquare") + } + } content: { + Continue() + } + Default { + Infix("+=") { + VariableExp("square") + VariableExp("diceRoll") + } + Infix("+=") { + VariableExp("square") + VariableExp("board[square]") + } + } + } + } + } + + // Generate Swift from DSL + var generated = program.generateCode() + + // Remove type annotations like ": Int =" for comparison to example code + generated = generated.normalize() + + // Use the expected Swift code as a string literal + let expected = """ + // Simple if statement + let temperature = 25 + if temperature > 30 { + print("It's hot outside!") + } + + // If-else statement + let score = 85 + if score >= 90 { + print("Excellent!") + } else if score >= 80 { + print("Good job!") + } else if score >= 70 { + print("Passing") + } else { + print("Needs improvement") + } + + // MARK: - Optional Binding with If + + // Using if let for optional binding + let possibleNumber = "123" + if let actualNumber = Int(possibleNumber) { + print("The string \"\\(possibleNumber)\" has an integer value of \\(actualNumber)") + } else { + print("The string \"\\(possibleNumber)\" could not be converted to an integer") + } + + // Multiple optional bindings + let possibleName: String? = "John" + let possibleAge: Int? = 30 + if let name = possibleName, let age = possibleAge { + print("\\(name) is \\(age) years old") + } + + // MARK: - Guard Statements + func greet(person: [String: String]) { + guard let name = person["name"] else { + print("No name provided") + return + } + + guard let age = person["age"], let ageInt = Int(age) else { + print("Invalid age provided") + return + } + + print("Hello \\(name), you are \\(ageInt) years old") + } + + // MARK: - Switch Statements + // Switch with range matching + let approximateCount = 62 + let countedThings = "moons orbiting Saturn" + let naturalCount: String + switch approximateCount { + case 0: + naturalCount = "no" + case 1..<5: + naturalCount = "a few" + case 5..<12: + naturalCount = "several" + case 12..<100: + naturalCount = "dozens of" + case 100..<1000: + naturalCount = "hundreds of" + default: + naturalCount = "many" + } + print("There are \\(naturalCount) \\(countedThings).") + + // Switch with tuple matching + let somePoint = (1, 1) + switch somePoint { + case (0, 0): + print("(0, 0) is at the origin") + case (_, 0): + print("(\\(somePoint.0), 0) is on the x-axis") + case (0, _): + print("(0, \\(somePoint.1)) is on the y-axis") + case (-2...2, -2...2): + print("(\\(somePoint.0), \\(somePoint.1)) is inside the box") + default: + print("(\\(somePoint.0), \\(somePoint.1)) is outside of the box") + } + + // Switch with value binding + let anotherPoint: (Int, Int) = (2, 0) + switch anotherPoint { + case (let x, 0): + print("on the x-axis with an x value of \\(x)") + case (0, let y): + print("on the y-axis with a y value of \\(y)") + case (let x, let y): + print("somewhere else at (\\(x), \\(y))") + } + + // MARK: - Fallthrough + // Using fallthrough in switch + let integerToDescribe = 5 + var description = "The number \\(integerToDescribe) is" + switch integerToDescribe { + case 2, 3, 5, 7, 11, 13, 17, 19: + description += " a prime number, and also" + fallthrough + default: + description += " an integer." + } + print(description) + + // MARK: - Labeled Statements + // Using labeled statements with break + let finalSquare = 25 + var board = [Int](repeating: 0, count: finalSquare + 1) + board[3] = 8 + board[6] = 11 + board[9] = 9 + board[10] = 2 + board[14] = -10 + board[19] = -11 + board[22] = -2 + board[24] = -8 + + var square = 0 + var diceRoll = 0 + while square != finalSquare { + diceRoll += 1 + if diceRoll == 7 { diceRoll = 1 } + switch square + diceRoll { + case finalSquare: + break + case let newSquare where newSquare > finalSquare: + continue + default: + square += diceRoll + square += board[square] + } + } + """ + .normalize() + + #expect(generated == expected) + } +} diff --git a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift new file mode 100644 index 0000000..ef823bb --- /dev/null +++ b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift @@ -0,0 +1,151 @@ +import Foundation +import Testing + +@testable import SyntaxKit + +@Suite internal struct ForLoopsExampleTests { + @Test("Completed for loops DSL generates expected Swift code") + internal func testCompletedForLoopsExample() throws { + // Build DSL equivalent of Examples/Completed/for_loops/dsl.swift + + let program = Group { + // MARK: - Basic For-in Loop + Variable( + .let, name: "names", + equals: Literal.array([ + Literal.string("Alice"), Literal.string("Bob"), Literal.string("Charlie"), + ]) + ) + .comment { + Line("MARK: - Basic For-in Loop") + Line("Simple for-in loop over an array") + } + + For( + VariableExp("name"), in: VariableExp("names"), + then: { + Call("print") { + ParameterExp(unlabeled: "\"Hello, \\(name)!\"") + } + }) + + // MARK: - For-in with Enumerated + Call("print") { + ParameterExp(unlabeled: "\"\\n=== For-in with Enumerated ===\"") + } + .comment { + Line("MARK: - For-in with Enumerated") + Line("For-in loop with enumerated() to get index and value") + } + For( + Tuple.patternCodeBlock([VariableExp("index"), VariableExp("name")]), + in: VariableExp("names").call("enumerated"), + then: { + Call("print") { + ParameterExp(unlabeled: "\"Index: \\(index), Name: \\(name)\"") + } + }) + + // MARK: - For-in with Where Clause + Call("print") { + ParameterExp(unlabeled: "\"\\n=== For-in with Where Clause ===\"") + } + .comment { + Line("MARK: - For-in with Where Clause") + Line("For-in loop with where clause") + } + Variable( + .let, name: "numbers", + equals: Literal.array([ + Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), + Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), + Literal.integer(9), Literal.integer(10), + ])) + + For( + VariableExp("number"), in: VariableExp("numbers"), + where: { + Infix("==") { + Infix("%") { + VariableExp("number") + Literal.integer(2) + } + Literal.integer(0) + } + }, + then: { + Call("print") { + ParameterExp(unlabeled: "\"Even number: \\(number)\"") + } + } + ) + + // MARK: - For-in with Dictionary + Call("print") { + ParameterExp(unlabeled: "\"\\n=== For-in with Dictionary ===\"") + } + .comment { + Line("MARK: - For-in with Dictionary") + Line("For-in loop over dictionary") + } + Variable( + .let, name: "scores", + equals: Literal.dictionary([ + (Literal.string("Alice"), Literal.integer(95)), + (Literal.string("Bob"), Literal.integer(87)), + (Literal.string("Charlie"), Literal.integer(92)), + ])) + + For( + Tuple.patternCodeBlock([VariableExp("name"), VariableExp("score")]), + in: VariableExp("scores"), + then: { + Call("print") { + ParameterExp(unlabeled: "\"\\(name): \\(score)\"") + } + }) + } + + // Generate Swift from DSL + var generated = program.generateCode() + + // Remove type annotations like ": Int =" for comparison to example code + generated = generated.normalize() + + // Use the expected Swift code as a string literal + let expected = """ + // MARK: - Basic For-in Loop + // Simple for-in loop over an array + let names = ["Alice", "Bob", "Charlie"] + for name in names { + print("Hello, \\(name)!") + } + + // MARK: - For-in with Enumerated + // For-in loop with enumerated() to get index and value + print("\\n=== For-in with Enumerated ===") + for (index, name) in names.enumerated() { + print("Index: \\(index), Name: \\(name)") + } + + // MARK: - For-in with Where Clause + // For-in loop with where clause + print("\\n=== For-in with Where Clause ===") + let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + for number in numbers where number % 2 == 0 { + print("Even number: \\(number)") + } + + // MARK: - For-in with Dictionary + // For-in loop over dictionary + print("\\n=== For-in with Dictionary ===") + let scores = ["Alice": 95, "Bob": 87, "Charlie": 92] + for (name, score) in scores { + print("\\(name): \\(score)") + } + """ + .normalize() + + #expect(generated == expected) + } +} diff --git a/Tests/SyntaxKitTests/AssertionMigrationTests.swift b/Tests/SyntaxKitTests/Unit/AssertionMigrationTests.swift similarity index 95% rename from Tests/SyntaxKitTests/AssertionMigrationTests.swift rename to Tests/SyntaxKitTests/Unit/AssertionMigrationTests.swift index 3c8d824..d6188b0 100644 --- a/Tests/SyntaxKitTests/AssertionMigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/AssertionMigrationTests.swift @@ -52,10 +52,10 @@ internal struct AssertionMigrationTests { let expected = """ struct Card { - enum Suit: Character { - case hearts = "♡" - case spades = "♠" - } + enum Suit: Character { + case hearts = "♡" + case spades = "♠" + } } """ diff --git a/Tests/SyntaxKitTests/AttributeTests.swift b/Tests/SyntaxKitTests/Unit/AttributeTests.swift similarity index 100% rename from Tests/SyntaxKitTests/AttributeTests.swift rename to Tests/SyntaxKitTests/Unit/AttributeTests.swift diff --git a/Tests/SyntaxKitTests/Unit/CallTests.swift b/Tests/SyntaxKitTests/Unit/CallTests.swift new file mode 100644 index 0000000..415df15 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/CallTests.swift @@ -0,0 +1,120 @@ +// +// CallTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SyntaxKit +import Testing + +@Suite internal struct CallTests { + @Test("Call without parameters generates correct syntax") + internal func testCallWithoutParameters() throws { + let call = Call("print") + let generated = call.generateCode() + #expect(generated.contains("print()")) + } + + @Test("Call with string parameter generates correct syntax") + internal func testCallWithStringParameter() throws { + let call = Call("print") { + ParameterExp(name: "", value: "\"Hello, World!\"") + } + let generated = call.generateCode() + #expect(generated.contains("print(\"Hello, World!\")")) + } + + @Test("Call with named parameter generates correct syntax") + internal func testCallWithNamedParameter() throws { + let call = Call("function") { + ParameterExp(name: "value", value: "42") + } + let generated = call.generateCode() + #expect(generated.contains("function(value:42)")) + } + + @Test("Call with multiple parameters generates correct syntax") + internal func testCallWithMultipleParameters() throws { + let call = Call("print") { + ParameterExp(name: "", value: "\"Count:\"") + ParameterExp(name: "count", value: "5") + } + let generated = call.generateCode() + #expect(generated.contains("print(\"Count:\", count:5)")) + } + + @Test("Call with string interpolation generates correct syntax") + internal func testCallWithStringInterpolation() throws { + let call = Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) vehicle...\"") + } + let generated = call.generateCode() + #expect(generated.contains("print(\"Starting \\(brand) vehicle...\")")) + } + + @Test("Call in function body generates correct syntax") + internal func testCallInFunctionBody() throws { + let function = Function("test") { + Call("print") { + ParameterExp(name: "", value: "\"Hello\"") + } + } + let generated = function.generateCode() + #expect(generated.contains("func test")) + #expect(generated.contains("print(\"Hello\")")) + } + + @Test("Protocol extension with Call generates correct syntax") + internal func testProtocolExtensionWithCall() throws { + let extSyntax = Extension("Vehicle") { + Function("start") { + Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) vehicle...\"") + } + } + } + let generated = extSyntax.generateCode() + #expect(generated.contains("extension Vehicle")) + #expect(generated.contains("func start")) + #expect(generated.contains("print(\"Starting \\(brand) vehicle...\")")) + } + + @Test("Struct with Call in method generates correct syntax") + internal func testStructWithCallInMethod() throws { + let structExp = Struct("Car") { + Function("start") { + Call("print") { + ParameterExp(name: "", value: "\"Starting \\(brand) car engine...\"") + } + } + } + let generated = structExp.generateCode() + #expect(generated.contains("struct Car")) + #expect(generated.contains("func start")) + #expect(generated.contains("print(\"Starting \\(brand) car engine...\")")) + } +} diff --git a/Tests/SyntaxKitTests/ClassTests.swift b/Tests/SyntaxKitTests/Unit/ClassTests.swift similarity index 80% rename from Tests/SyntaxKitTests/ClassTests.swift rename to Tests/SyntaxKitTests/Unit/ClassTests.swift index 8c5bc1b..f24de2e 100644 --- a/Tests/SyntaxKitTests/ClassTests.swift +++ b/Tests/SyntaxKitTests/Unit/ClassTests.swift @@ -5,14 +5,14 @@ import Testing internal struct ClassTests { @Test internal func testClassWithInheritance() { let carClass = Class("Car") { - Variable(.var, name: "brand", type: "String") - Variable(.var, name: "numberOfWheels", type: "Int") + Variable(.var, name: "brand", type: "String").withExplicitType() + Variable(.var, name: "numberOfWheels", type: "Int").withExplicitType() }.inherits("Vehicle") let expected = """ class Car: Vehicle { - var brand: String - var numberOfWheels: Int + var brand: String + var numberOfWheels: Int } """ @@ -36,12 +36,12 @@ internal struct ClassTests { @Test internal func testClassWithGenerics() { let genericClass = Class("Container") { - Variable(.var, name: "value", type: "T") + Variable(.var, name: "value", type: "T").withExplicitType() }.generic("T") let expected = """ class Container { - var value: T + var value: T } """ @@ -52,14 +52,14 @@ internal struct ClassTests { @Test internal func testClassWithMultipleGenerics() { let multiGenericClass = Class("Pair") { - Variable(.var, name: "first", type: "T") - Variable(.var, name: "second", type: "U") + Variable(.var, name: "first", type: "T").withExplicitType() + Variable(.var, name: "second", type: "U").withExplicitType() }.generic("T", "U") let expected = """ class Pair { - var first: T - var second: U + var first: T + var second: U } """ @@ -70,12 +70,12 @@ internal struct ClassTests { @Test internal func testFinalClass() { let finalClass = Class("FinalClass") { - Variable(.var, name: "value", type: "String") + Variable(.var, name: "value", type: "String").withExplicitType() }.final() let expected = """ final class FinalClass { - var value: String + var value: String } """ @@ -86,12 +86,12 @@ internal struct ClassTests { @Test internal func testClassWithMultipleInheritance() { let classWithMultipleInheritance = Class("AdvancedVehicle") { - Variable(.var, name: "speed", type: "Int") + Variable(.var, name: "speed", type: "Int").withExplicitType() }.inherits("Vehicle") let expected = """ class AdvancedVehicle: Vehicle { - var speed: Int + var speed: Int } """ @@ -102,12 +102,12 @@ internal struct ClassTests { @Test internal func testClassWithGenericsAndInheritance() { let genericClassWithInheritance = Class("GenericContainer") { - Variable(.var, name: "items", type: "[T]") + Variable(.var, name: "items", type: "[T]").withExplicitType() }.generic("T").inherits("Collection") let expected = """ class GenericContainer: Collection { - var items: [T] + var items: [T] } """ @@ -118,12 +118,12 @@ internal struct ClassTests { @Test internal func testFinalClassWithInheritanceAndGenerics() { let finalGenericClass = Class("FinalGenericClass") { - Variable(.var, name: "value", type: "T") + Variable(.var, name: "value", type: "T").withExplicitType() }.generic("T").inherits("BaseClass").final() let expected = """ final class FinalGenericClass: BaseClass { - var value: T + var value: T } """ @@ -146,9 +146,9 @@ internal struct ClassTests { let expected = """ class Calculator { - func add(a: Int, b: Int) -> Int { - return a + b - } + func add(a: Int, b: Int) -> Int { + return a + b + } } """ diff --git a/Tests/SyntaxKitTests/CodeStyleMigrationTests.swift b/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift similarity index 97% rename from Tests/SyntaxKitTests/CodeStyleMigrationTests.swift rename to Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift index 8a9daa8..ab867ee 100644 --- a/Tests/SyntaxKitTests/CodeStyleMigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift @@ -50,8 +50,8 @@ internal struct CodeStyleMigrationTests { @Test func testMultilineStringFormatting() { let expected = """ struct TestStruct { - let value: String - var count: Int + let value: String + var count: Int } """ diff --git a/Tests/SyntaxKitTests/Unit/ConditionalsTests.swift b/Tests/SyntaxKitTests/Unit/ConditionalsTests.swift new file mode 100644 index 0000000..f2f87f6 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ConditionalsTests.swift @@ -0,0 +1,50 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct ConditionalsTests { + @Test("If / else-if / else chain generates correct syntax") + internal func testIfElseChain() throws { + // Arrange: build the DSL example using the updated APIs + let conditional = Group { + Variable(.let, name: "score", type: "Int", equals: "85") + + If { + Infix(">=") { + VariableExp("score") + Literal.integer(90) + } + } then: { + Call("print") { + ParameterExp(name: "", value: "\"Excellent!\"") + } + } else: { + If { + Infix(">=") { + VariableExp("score") + Literal.integer(80) + } + } then: { + Call("print") { + ParameterExp(name: "", value: "\"Good job!\"") + } + } + + Then { + Call("print") { + ParameterExp(name: "", value: "\"Needs improvement\"") + } + } + } + } + + // Act + let generated = conditional.generateCode().normalize() + + // Assert key structure is present + #expect(generated.contains("let score".normalize())) + #expect(generated.contains("if score >= 90".normalize())) + #expect(generated.contains("else if score >= 80".normalize())) + #expect(generated.contains("else {".normalize())) + } +} diff --git a/Tests/SyntaxKitTests/EdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift similarity index 97% rename from Tests/SyntaxKitTests/EdgeCaseTests.swift rename to Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift index a2b63b6..55c7c96 100644 --- a/Tests/SyntaxKitTests/EdgeCaseTests.swift +++ b/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift @@ -124,8 +124,8 @@ internal struct EdgeCaseTests { @Test("CodeBlock generateCode with CodeBlockItemListSyntax") internal func testCodeBlockGenerateCodeWithItemList() throws { let group = Group { - Variable(.let, name: "x", type: "Int", equals: "1") - Variable(.let, name: "y", type: "Int", equals: "2") + Variable(.let, name: "x", type: "Int", equals: 1).withExplicitType() + Variable(.let, name: "y", type: "Int", equals: 2).withExplicitType() } let generated = group.generateCode() @@ -135,7 +135,7 @@ internal struct EdgeCaseTests { @Test("CodeBlock generateCode with single declaration") internal func testCodeBlockGenerateCodeWithSingleDeclaration() throws { - let variable = Variable(.let, name: "x", type: "Int", equals: "1") + let variable = Variable(.let, name: "x", type: "Int", equals: 1).withExplicitType() let generated = variable.generateCode() #expect(generated.contains("let x : Int = 1")) @@ -143,7 +143,7 @@ internal struct EdgeCaseTests { @Test("CodeBlock generateCode with single statement") internal func testCodeBlockGenerateCodeWithSingleStatement() throws { - let assignment = Assignment("x", "42") + let assignment = Assignment("x", Literal.integer(42)) let generated = assignment.generateCode() #expect(generated.contains("x = 42")) diff --git a/Tests/SyntaxKitTests/ExtensionTests.swift b/Tests/SyntaxKitTests/Unit/ExtensionTests.swift similarity index 88% rename from Tests/SyntaxKitTests/ExtensionTests.swift rename to Tests/SyntaxKitTests/Unit/ExtensionTests.swift index ee57490..f2e0cb0 100644 --- a/Tests/SyntaxKitTests/ExtensionTests.swift +++ b/Tests/SyntaxKitTests/Unit/ExtensionTests.swift @@ -36,7 +36,7 @@ internal struct ExtensionTests { @Test internal func testBasicExtension() { let extensionDecl = Extension("String") { - Variable(.let, name: "test", type: "Int", equals: "42") + Variable(.let, name: "test", type: "Int", equals: Literal.integer(42)).withExplicitType() } let generated = extensionDecl.generateCode().normalize() @@ -47,8 +47,9 @@ internal struct ExtensionTests { @Test internal func testExtensionWithMultipleMembers() { let extensionDecl = Extension("Array") { - Variable(.let, name: "isEmpty", type: "Bool", equals: "true") - Variable(.let, name: "count", type: "Int", equals: "0") + Variable(.let, name: "isEmpty", type: "Bool", equals: Literal.boolean(true)) + .withExplicitType() + Variable(.let, name: "count", type: "Int", equals: Literal.integer(0)).withExplicitType() } let generated = extensionDecl.generateCode().normalize() @@ -85,7 +86,8 @@ internal struct ExtensionTests { @Test internal func testExtensionWithoutInheritance() { let extensionDecl = Extension("MyType") { - Variable(.let, name: "constant", type: "String", equals: "value") + Variable(.let, name: "constant", type: "String", equals: Literal.ref("value")) + .withExplicitType() } let generated = extensionDecl.generateCode().normalize() @@ -103,8 +105,8 @@ internal struct ExtensionTests { let extensionDecl = Extension("TestEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: array).static() - Variable(.let, name: "lookup", equals: dict).static() + Variable(.let, name: "mappedValues", equals: array).withExplicitType().static() + Variable(.let, name: "lookup", equals: dict).withExplicitType().static() }.inherits("MappedValueRepresentable", "MappedValueRepresented") let generated = extensionDecl.generateCode().normalize() @@ -150,7 +152,7 @@ internal struct ExtensionTests { @Test internal func testExtensionWithSpecialCharactersInName() { let extensionDecl = Extension("MyType") { - Variable(.let, name: "generic", type: "T", equals: "nil") + Variable(.let, name: "generic", type: "T", equals: Literal.nil).withExplicitType() } let generated = extensionDecl.generateCode().normalize() @@ -161,7 +163,7 @@ internal struct ExtensionTests { @Test internal func testInheritsMethodReturnsNewInstance() { let original = Extension("Test") { - Variable(.let, name: "value", type: "Int", equals: "42") + Variable(.let, name: "value", type: "Int", equals: Literal.integer(42)).withExplicitType() } let withInheritance = original.inherits("Protocol1", "Protocol2") diff --git a/Tests/SyntaxKitTests/Unit/ForLoopTests.swift b/Tests/SyntaxKitTests/Unit/ForLoopTests.swift new file mode 100644 index 0000000..f5fd0b2 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ForLoopTests.swift @@ -0,0 +1,45 @@ +import Testing + +@testable import SyntaxKit + +@Suite +final class ForLoopTests { + @Test + func testSimpleForInLoop() { + let forLoop = For( + VariableExp("item"), + in: VariableExp("items"), + then: { + Call("print") { + ParameterExp(name: "", value: "item") + } + } + ) + let generated = forLoop.syntax.description + let expected = "for item in items {\n print(item)\n}" + #expect(generated.contains("for item in items")) + #expect(generated.contains("print(item)")) + } + + @Test + func testForInWithWhereClause() { + let forLoop = For( + VariableExp("number"), + in: VariableExp("numbers"), + where: { + Infix("%") { + VariableExp("number") + Literal.integer(2) + } + }, + then: { + Call("print") { + ParameterExp(name: "", value: "number") + } + } + ) + let generated = forLoop.syntax.description + #expect(generated.contains("for number in numbers where number % 2")) + #expect(generated.contains("print(number)")) + } +} diff --git a/Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift b/Tests/SyntaxKitTests/Unit/FrameworkCompatibilityTests.swift similarity index 96% rename from Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift rename to Tests/SyntaxKitTests/Unit/FrameworkCompatibilityTests.swift index 33f0de8..fe34cd5 100644 --- a/Tests/SyntaxKitTests/FrameworkCompatibilityTests.swift +++ b/Tests/SyntaxKitTests/Unit/FrameworkCompatibilityTests.swift @@ -124,8 +124,8 @@ internal struct FrameworkCompatibilityTests { @Test internal func testNoRegressionInCodeGeneration() { // Ensure migration doesn't introduce regressions let simpleStruct = Struct("Point") { - Variable(.var, name: "x", type: "Double", equals: "0.0") - Variable(.var, name: "y", type: "Double", equals: "0.0") + Variable(.var, name: "x", type: "Double", equals: 0.0).withExplicitType() + Variable(.var, name: "y", type: "Double", equals: 0.0).withExplicitType() } let generated = simpleStruct.generateCode().normalize() diff --git a/Tests/SyntaxKitTests/FunctionTests.swift b/Tests/SyntaxKitTests/Unit/FunctionTests.swift similarity index 90% rename from Tests/SyntaxKitTests/FunctionTests.swift rename to Tests/SyntaxKitTests/Unit/FunctionTests.swift index 50f0da9..5ae2c2f 100644 --- a/Tests/SyntaxKitTests/FunctionTests.swift +++ b/Tests/SyntaxKitTests/Unit/FunctionTests.swift @@ -15,7 +15,7 @@ internal struct FunctionTests { let expected = """ func calculateSum(a: Int, b: Int) -> Int { - return a + b + return a + b } """ @@ -36,14 +36,14 @@ internal struct FunctionTests { ) { Return { Init("MyType") { - Parameter(name: "value", type: "String") + ParameterExp(name: "value", value: Literal.ref("value")) } } }.static() let expected = """ static func createInstance(value: String) -> MyType { - return MyType(value: value) + return MyType(value: value) } """ @@ -62,12 +62,12 @@ internal struct FunctionTests { Parameter(name: "newValue", type: "String") } ) { - Assignment("value", "newValue") + Assignment("value", Literal.ref("newValue")) }.mutating() let expected = """ mutating func updateValue(newValue: String) { - value = newValue + value = newValue } """ diff --git a/Tests/SyntaxKitTests/LiteralTests.swift b/Tests/SyntaxKitTests/Unit/LiteralTests.swift similarity index 100% rename from Tests/SyntaxKitTests/LiteralTests.swift rename to Tests/SyntaxKitTests/Unit/LiteralTests.swift diff --git a/Tests/SyntaxKitTests/LiteralValueTests.swift b/Tests/SyntaxKitTests/Unit/LiteralValueTests.swift similarity index 51% rename from Tests/SyntaxKitTests/LiteralValueTests.swift rename to Tests/SyntaxKitTests/Unit/LiteralValueTests.swift index ce7cd09..f28ab60 100644 --- a/Tests/SyntaxKitTests/LiteralValueTests.swift +++ b/Tests/SyntaxKitTests/Unit/LiteralValueTests.swift @@ -108,4 +108,109 @@ internal struct LiteralValueTests { #expect(literal2.contains("2: \"b\"")) #expect(literal2.contains("3: \"c\"")) } + + // MARK: - TupleLiteral Tests + + @Test internal func testTupleLiteralTypeName() { + let tuple1 = TupleLiteral([.int(1), .int(2)]) + #expect(tuple1.typeName == "(Int, Int)") + + let tuple2 = TupleLiteral([.string("hello"), .int(42), .boolean(true)]) + #expect(tuple2.typeName == "(String, Int, Bool)") + + let tuple3 = TupleLiteral([.int(1), nil, .string("test")]) + #expect(tuple3.typeName == "(Int, Any, String)") + + let tuple4 = TupleLiteral([nil, nil]) + #expect(tuple4.typeName == "(Any, Any)") + } + + @Test internal func testTupleLiteralString() { + let tuple1 = TupleLiteral([.int(1), .int(2)]) + #expect(tuple1.literalString == "(1, 2)") + + let tuple2 = TupleLiteral([.string("hello"), .int(42), .boolean(true)]) + #expect(tuple2.literalString == "(\"hello\", 42, true)") + + let tuple3 = TupleLiteral([.int(1), nil, .string("test")]) + #expect(tuple3.literalString == "(1, _, \"test\")") + + let tuple4 = TupleLiteral([nil, nil]) + #expect(tuple4.literalString == "(_, _)") + + let tuple5 = TupleLiteral([.float(3.14), .nil]) + #expect(tuple5.literalString == "(3.14, nil)") + } + + @Test internal func testTupleLiteralWithNestedTuples() { + let nestedTuple = TupleLiteral([.int(1), .tuple([.string("nested"), .int(2)])]) + #expect(nestedTuple.typeName == "(Int, Any)") + #expect(nestedTuple.literalString == "(1, (\"nested\", 2))") + } + + @Test internal func testTupleLiteralWithRef() { + let tuple = TupleLiteral([.ref("variable"), .int(42)]) + #expect(tuple.typeName == "(Any, Int)") + #expect(tuple.literalString == "(variable, 42)") + } + + @Test internal func testEmptyTupleLiteral() { + let tuple = TupleLiteral([]) + #expect(tuple.typeName == "()") + #expect(tuple.literalString == "()") + } + + // MARK: - TupleLiteral Code Generation Tests + + @Test internal func testVariableWithTupleLiteral() { + let tuple = TupleLiteral([.int(1), .int(2)]) + let variable = Variable(.let, name: "point", equals: tuple) + + let generated = variable.syntax.description + #expect(generated.contains("let point = (1, 2)")) + #expect(generated.contains("point")) + } + + @Test internal func testVariableWithTupleLiteralWithExplicitType() { + let tuple = TupleLiteral([.int(1), .int(2)]) + let variable = Variable(.let, name: "point", equals: tuple).withExplicitType() + + let generated = variable.syntax.description + #expect(generated.contains("let point : (Int, Int) = (1, 2)")) + #expect(generated.contains("point")) + } + + @Test internal func testVariableWithComplexTupleLiteral() { + let tuple = TupleLiteral([.string("hello"), .int(42), .boolean(true)]) + let variable = Variable(.let, name: "data", equals: tuple).withExplicitType() + + let generated = variable.syntax.description + #expect(generated.contains("let data : (String, Int, Bool) = (\"hello\", 42, true)")) + #expect(generated.contains("data")) + } + + @Test internal func testVariableWithTupleLiteralWithWildcards() { + let tuple = TupleLiteral([.int(1), nil, .string("test")]) + let variable = Variable(.let, name: "partial", equals: tuple).withExplicitType() + + let generated = variable.syntax.description + #expect(generated.contains("let partial : (Int, Any, String) = (1, _, \"test\")")) + #expect(generated.contains("partial")) + } + + @Test internal func testLiteralAsTupleLiteralConversion() { + let literal = Literal.tuple([.int(1), .int(2)]) + let tupleLiteral = literal.asTupleLiteral + + #expect(tupleLiteral != nil) + #expect(tupleLiteral?.typeName == "(Int, Int)") + #expect(tupleLiteral?.literalString == "(1, 2)") + } + + @Test internal func testNonTupleLiteralAsTupleLiteralConversion() { + let literal = Literal.int(42) + let tupleLiteral = literal.asTupleLiteral + + #expect(tupleLiteral == nil) + } } diff --git a/Tests/SyntaxKitTests/MainApplicationTests.swift b/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift similarity index 94% rename from Tests/SyntaxKitTests/MainApplicationTests.swift rename to Tests/SyntaxKitTests/Unit/MainApplicationTests.swift index 397838e..d47974f 100644 --- a/Tests/SyntaxKitTests/MainApplicationTests.swift +++ b/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift @@ -74,10 +74,10 @@ internal struct MainApplicationTests { for index in 1...50 { largeCode += """ struct Struct\(index) { - let property\(index): String - func method\(index)() -> String { - return "value\(index)" - } + let property\(index): String + func method\(index)() -> String { + return "value\(index)" + } } """ @@ -146,16 +146,16 @@ internal struct MainApplicationTests { internal func testMainApplicationIntegrationWithComplexSwiftCode() throws { let code = """ @objc class MyClass: NSObject { - @Published var property: String = "default" + @Published var property: String = "default" - func method(@escaping completion: @escaping (String) -> Void) { - completion("result") - } + func method(@escaping completion: @escaping (String) -> Void) { + completion("result") + } - enum NestedEnum: Int { - case first = 1 - case second = 2 - } + enum NestedEnum: Int { + case first = 1 + case second = 2 + } } """ diff --git a/Tests/SyntaxKitTests/MigrationTests.swift b/Tests/SyntaxKitTests/Unit/MigrationTests.swift similarity index 95% rename from Tests/SyntaxKitTests/MigrationTests.swift rename to Tests/SyntaxKitTests/Unit/MigrationTests.swift index b97b32d..ed00bc1 100644 --- a/Tests/SyntaxKitTests/MigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/MigrationTests.swift @@ -59,12 +59,12 @@ internal struct MigrationTests { let expected = """ struct BlackjackCard { - enum Suit: Character { - case spades = "♠" - case hearts = "♡" - case diamonds = "♢" - case clubs = "♣" - } + enum Suit: Character { + case spades = "♠" + case hearts = "♡" + case diamonds = "♢" + case clubs = "♣" + } } """ diff --git a/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift similarity index 92% rename from Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift rename to Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift index af6106d..3870889 100644 --- a/Tests/SyntaxKitTests/OptionsMacroIntegrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift @@ -40,7 +40,7 @@ internal struct OptionsMacroIntegrationTests { let extensionDecl = Extension("MockDictionaryEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: keyValues).static() + Variable(.let, name: "mappedValues", equals: keyValues).withExplicitType().static() }.inherits("MappedValueRepresentable", "MappedValueRepresented") let generated = extensionDecl.generateCode().normalize() @@ -62,7 +62,7 @@ internal struct OptionsMacroIntegrationTests { let extensionDecl = Extension("Color") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: caseNames).static() + Variable(.let, name: "mappedValues", equals: caseNames).withExplicitType().static() }.inherits("MappedValueRepresentable", "MappedValueRepresented") let generated = extensionDecl.generateCode().normalize() @@ -86,10 +86,12 @@ internal struct OptionsMacroIntegrationTests { let mappedValuesVariable: Variable if hasRawValues { let keyValues: [Int: String] = [1: "first", 2: "second", 3: "third"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues).static() + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues) + .withExplicitType().static() } else { let caseNames: [String] = ["first", "second", "third"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames).static() + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames) + .withExplicitType().static() } // Step 3: Create the extension @@ -119,10 +121,12 @@ internal struct OptionsMacroIntegrationTests { let mappedValuesVariable: Variable if hasRawValues { let keyValues: [Int: String] = [1: "first", 2: "second"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues).static() + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues) + .withExplicitType().static() } else { let caseNames: [String] = ["first", "second"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames).static() + mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames) + .withExplicitType().static() } let extensionDecl = Extension(enumName) { @@ -145,7 +149,7 @@ internal struct OptionsMacroIntegrationTests { let extensionDecl = Extension("EmptyEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: caseNames).static() + Variable(.let, name: "mappedValues", equals: caseNames).withExplicitType().static() }.inherits("MappedValueRepresentable", "MappedValueRepresented") let generated = extensionDecl.generateCode().normalize() @@ -161,7 +165,7 @@ internal struct OptionsMacroIntegrationTests { let extensionDecl = Extension("EmptyDictEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: keyValues).static() + Variable(.let, name: "mappedValues", equals: keyValues).withExplicitType().static() }.inherits("MappedValueRepresentable", "MappedValueRepresented") let generated = extensionDecl.generateCode().normalize() @@ -170,7 +174,7 @@ internal struct OptionsMacroIntegrationTests { generated.contains( "extension EmptyDictEnum: MappedValueRepresentable, MappedValueRepresented")) #expect(generated.contains("typealias MappedType = String")) - #expect(generated.contains("static let mappedValues: [Int: String] = []")) + #expect(generated.contains("static let mappedValues: [Int: String] = [: ]")) } @Test internal func testSpecialCharactersInCaseNames() { @@ -178,7 +182,7 @@ internal struct OptionsMacroIntegrationTests { let extensionDecl = Extension("SpecialEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: caseNames).static() + Variable(.let, name: "mappedValues", equals: caseNames).withExplicitType().static() }.inherits("MappedValueRepresentable", "MappedValueRepresented") let generated = extensionDecl.generateCode().normalize() @@ -208,7 +212,7 @@ internal struct OptionsMacroIntegrationTests { #expect(dict.literalString.contains("2: \"b\"")) // Test Variable with static support - let staticVar = Variable(.let, name: "test", equals: array).static() + let staticVar = Variable(.let, name: "test", equals: array).withExplicitType().static() let staticGenerated = staticVar.generateCode().normalize() #expect(staticGenerated.contains("static let test: [String] = [\"a\", \"b\", \"c\"]")) diff --git a/Tests/SyntaxKitTests/Unit/PatternConvertibleTests.swift b/Tests/SyntaxKitTests/Unit/PatternConvertibleTests.swift new file mode 100644 index 0000000..1e5008f --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/PatternConvertibleTests.swift @@ -0,0 +1,89 @@ +// +// PatternConvertibleTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +internal struct PatternConvertibleTests { + // MARK: - Let Binding Pattern Tests + + @Test internal func testLetBindingPattern() { + let pattern = Pattern.let("x") + let syntax = pattern.patternSyntax + + let generated = syntax.description + #expect(generated.contains("let x")) + } + + @Test internal func testLetBindingPatternInTuple() { + let tuplePattern = Tuple.pattern([Pattern.let("x"), 0]) + let syntax = tuplePattern.patternSyntax + + let generated = syntax.description + #expect(generated.contains("(let x, 0)")) + } + + @Test internal func testLetBindingPatternInSwitchCase() { + let switchCase = SwitchCase(Tuple.pattern([Pattern.let("x"), Pattern.let("y")])) { + Call("print") { + ParameterExp(name: "", value: "\"somewhere else at (\\(x), \\(y))\"") + } + } + + let generated = switchCase.generateCode() + #expect(generated.contains("case (let x, let y):")) + #expect(generated.contains("print(\"somewhere else at (\\(x), \\(y))\")")) + } + + @Test internal func testLetBindingPatternWithSingleElement() { + let pattern = Pattern.let("value") + let syntax = pattern.patternSyntax + + let generated = syntax.description + #expect(generated.contains("let value")) + } + + @Test internal func testLetBindingPatternInComplexTuple() { + let tuplePattern = Tuple.pattern([Pattern.let("x"), 0, Pattern.let("y")]) + let syntax = tuplePattern.patternSyntax + + let generated = syntax.description + #expect(generated.contains("(let x, 0, let y)")) + } + + @Test internal func testLetBindingPatternWithWildcard() { + let tuplePattern = Tuple.pattern([Pattern.let("x"), nil, Pattern.let("y")]) + let syntax = tuplePattern.patternSyntax + + let generated = syntax.description + #expect(generated.contains("(let x, _, let y)")) + } +} diff --git a/Tests/SyntaxKitTests/ProtocolTests.swift b/Tests/SyntaxKitTests/Unit/ProtocolTests.swift similarity index 88% rename from Tests/SyntaxKitTests/ProtocolTests.swift rename to Tests/SyntaxKitTests/Unit/ProtocolTests.swift index dec6071..4d67358 100644 --- a/Tests/SyntaxKitTests/ProtocolTests.swift +++ b/Tests/SyntaxKitTests/Unit/ProtocolTests.swift @@ -14,11 +14,11 @@ internal struct ProtocolTests { let expected = """ protocol Vehicle { - var numberOfWheels: Int { get } - var brand: String { get set } - func start() - func stop() - func speed() -> Int + var numberOfWheels: Int { get } + var brand: String { get set } + func start() + func stop() + func speed() -> Int } """ @@ -47,7 +47,7 @@ internal struct ProtocolTests { let expected = """ protocol MyProtocol: Equatable, Hashable { - var value: String { get set } + var value: String { get set } } """ @@ -66,7 +66,7 @@ internal struct ProtocolTests { let expected = """ protocol Calculator { - func add(a: Int, b: Int) -> Int + func add(a: Int, b: Int) -> Int } """ @@ -82,7 +82,7 @@ internal struct ProtocolTests { let expected = """ protocol Factory { - static func create() -> Self + static func create() -> Self } """ @@ -98,7 +98,7 @@ internal struct ProtocolTests { let expected = """ protocol Resettable { - mutating func reset() + mutating func reset() } """ @@ -115,7 +115,7 @@ internal struct ProtocolTests { let expected = """ protocol TestProtocol { - var readOnlyProperty: String { get } + var readOnlyProperty: String { get } } """ @@ -132,7 +132,7 @@ internal struct ProtocolTests { let expected = """ protocol TestProtocol { - var readWriteProperty: Int { get set } + var readWriteProperty: Int { get set } } """ @@ -152,7 +152,7 @@ internal struct ProtocolTests { let expected = """ protocol TestProtocol { - func process(input: String, options: ProcessingOptions = ProcessingOptions()) -> String + func process(input: String, options: ProcessingOptions = ProcessingOptions()) -> String } """ @@ -174,11 +174,11 @@ internal struct ProtocolTests { let expected = """ protocol ComplexProtocol: Identifiable { - var id: UUID { get } - var name: String { get set } - mutating func initialize() - func process(input: Data) -> Result - static func factory() -> Self + var id: UUID { get } + var name: String { get set } + mutating func initialize() + func process(input: Data) -> Result + static func factory() -> Self } """ diff --git a/Tests/SyntaxKitTests/String+Normalize.swift b/Tests/SyntaxKitTests/Unit/String+Normalize.swift similarity index 79% rename from Tests/SyntaxKitTests/String+Normalize.swift rename to Tests/SyntaxKitTests/Unit/String+Normalize.swift index bc1c614..8b1251b 100644 --- a/Tests/SyntaxKitTests/String+Normalize.swift +++ b/Tests/SyntaxKitTests/Unit/String+Normalize.swift @@ -3,7 +3,6 @@ import Foundation extension String { internal func normalize() -> String { self - .replacingOccurrences(of: "//.*$", with: "", options: .regularExpression) .replacingOccurrences(of: "\\s*:\\s*", with: ": ", options: .regularExpression) .replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) .trimmingCharacters(in: .whitespacesAndNewlines) diff --git a/Tests/SyntaxKitTests/StructTests.swift b/Tests/SyntaxKitTests/Unit/StructTests.swift similarity index 71% rename from Tests/SyntaxKitTests/StructTests.swift rename to Tests/SyntaxKitTests/Unit/StructTests.swift index 61ba952..7ea5bf8 100644 --- a/Tests/SyntaxKitTests/StructTests.swift +++ b/Tests/SyntaxKitTests/Unit/StructTests.swift @@ -5,7 +5,7 @@ import Testing internal struct StructTests { @Test internal func testGenericStruct() { let stackStruct = Struct("Stack") { - Variable(.var, name: "items", type: "[Element]", equals: "[]") + Variable(.var, name: "items", type: "[Element]", equals: Literal.array([])).withExplicitType() Function("push") { Parameter(name: "item", type: "Element", isUnnamed: true) @@ -34,27 +34,27 @@ internal struct StructTests { let expectedCode = """ struct Stack { - var items: [Element] = [] + var items: [Element] = [] - mutating func push(_ item: Element) { - items.append(item) - } + mutating func push(_ item: Element) { + items.append(item) + } - mutating func pop() -> Element? { - return items.popLast() - } + mutating func pop() -> Element? { + return items.popLast() + } - func peek() -> Element? { - return items.last - } + func peek() -> Element? { + return items.last + } - var isEmpty: Bool { - return items.isEmpty - } + var isEmpty: Bool { + return items.isEmpty + } - var count: Int { - return items.count - } + var count: Int { + return items.count + } } """ @@ -65,12 +65,12 @@ internal struct StructTests { @Test internal func testGenericStructWithInheritance() { let containerStruct = Struct("Container") { - Variable(.var, name: "value", type: "T") + Variable(.var, name: "value", type: "T").withExplicitType() }.generic("T").inherits("Equatable") let expectedCode = """ struct Container: Equatable { - var value: T + var value: T } """ @@ -81,14 +81,14 @@ internal struct StructTests { @Test internal func testNonGenericStruct() { let simpleStruct = Struct("Point") { - Variable(.var, name: "x", type: "Double") - Variable(.var, name: "y", type: "Double") + Variable(.var, name: "x", type: "Double").withExplicitType() + Variable(.var, name: "y", type: "Double").withExplicitType() } let expectedCode = """ struct Point { - var x: Double - var y: Double + var x: Double + var y: Double } """ diff --git a/Tests/SyntaxKitTests/TypeAliasTests.swift b/Tests/SyntaxKitTests/Unit/TypeAliasTests.swift similarity index 96% rename from Tests/SyntaxKitTests/TypeAliasTests.swift rename to Tests/SyntaxKitTests/Unit/TypeAliasTests.swift index 62f47cf..cd0eb1c 100644 --- a/Tests/SyntaxKitTests/TypeAliasTests.swift +++ b/Tests/SyntaxKitTests/Unit/TypeAliasTests.swift @@ -67,7 +67,8 @@ internal struct TypeAliasTests { @Test internal func testTypeAliasInExtension() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "test", type: "MappedType", equals: "value") + Variable(.let, name: "test", type: "MappedType", equals: Literal.ref("value")) + .withExplicitType() } let generated = extensionDecl.generateCode().normalize() @@ -80,7 +81,7 @@ internal struct TypeAliasTests { @Test internal func testTypeAliasInStruct() { let structDecl = Struct("Container") { TypeAlias("ElementType", equals: "String") - Variable(.let, name: "element", type: "ElementType") + Variable(.let, name: "element", type: "ElementType").withExplicitType() } let generated = structDecl.generateCode().normalize() @@ -149,7 +150,7 @@ internal struct TypeAliasTests { @Test internal func testTypeAliasWithStaticVariable() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: ["a", "b", "c"]).static() + Variable(.let, name: "mappedValues", equals: ["a", "b", "c"]).withExplicitType().static() }.inherits("MappedValueRepresentable") let generated = extensionDecl.generateCode().normalize() @@ -162,7 +163,7 @@ internal struct TypeAliasTests { @Test internal func testTypeAliasWithDictionaryVariable() { let extensionDecl = Extension("MyEnum") { TypeAlias("MappedType", equals: "String") - Variable(.let, name: "mappedValues", equals: [1: "a", 2: "b"]).static() + Variable(.let, name: "mappedValues", equals: [1: "a", 2: "b"]).withExplicitType().static() }.inherits("MappedValueRepresentable") let generated = extensionDecl.generateCode().normalize() diff --git a/Tests/SyntaxKitTests/VariableStaticTests.swift b/Tests/SyntaxKitTests/Unit/VariableStaticTests.swift similarity index 87% rename from Tests/SyntaxKitTests/VariableStaticTests.swift rename to Tests/SyntaxKitTests/Unit/VariableStaticTests.swift index 54612d1..3ee8dc0 100644 --- a/Tests/SyntaxKitTests/VariableStaticTests.swift +++ b/Tests/SyntaxKitTests/Unit/VariableStaticTests.swift @@ -35,7 +35,9 @@ internal struct VariableStaticTests { // MARK: - Static Variable Tests @Test internal func testStaticVariableWithStringLiteral() { - let variable = Variable(.let, name: "test", type: "String", equals: "hello").static() + let variable = Variable(.let, name: "test", type: "String", equals: Literal.ref("hello")) + .withExplicitType() + .static() let generated = variable.generateCode().normalize() #expect(generated.contains("static let test: String = hello")) @@ -43,7 +45,7 @@ internal struct VariableStaticTests { @Test internal func testStaticVariableWithArrayLiteral() { let array: [String] = ["a", "b", "c"] - let variable = Variable(.let, name: "mappedValues", equals: array).static() + let variable = Variable(.let, name: "mappedValues", equals: array).withExplicitType().static() let generated = variable.generateCode().normalize() #expect(generated.contains("static let mappedValues: [String] = [\"a\", \"b\", \"c\"]")) @@ -51,7 +53,7 @@ internal struct VariableStaticTests { @Test internal func testStaticVariableWithDictionaryLiteral() { let dict: [Int: String] = [1: "a", 2: "b", 3: "c"] - let variable = Variable(.let, name: "mappedValues", equals: dict).static() + let variable = Variable(.let, name: "mappedValues", equals: dict).withExplicitType().static() let generated = variable.generateCode().normalize() #expect(generated.contains("static let mappedValues: [Int: String]")) @@ -61,7 +63,9 @@ internal struct VariableStaticTests { } @Test internal func testStaticVariableWithVar() { - let variable = Variable(.var, name: "counter", type: "Int", equals: "0").static() + let variable = Variable(.var, name: "counter", type: "Int", equals: Literal.integer(0)) + .withExplicitType() + .static() let generated = variable.generateCode().normalize() #expect(generated.contains("static var counter: Int = 0")) @@ -71,7 +75,7 @@ internal struct VariableStaticTests { @Test internal func testNonStaticVariableWithLiteral() { let array: [String] = ["x", "y", "z"] - let variable = Variable(.let, name: "values", equals: array) + let variable = Variable(.let, name: "values", equals: array).withExplicitType() let generated = variable.generateCode().normalize() #expect(generated.contains("let values: [String] = [\"x\", \"y\", \"z\"]")) @@ -80,7 +84,7 @@ internal struct VariableStaticTests { @Test internal func testNonStaticVariableWithDictionary() { let dict: [Int: String] = [10: "ten", 20: "twenty"] - let variable = Variable(.let, name: "lookup", equals: dict) + let variable = Variable(.let, name: "lookup", equals: dict).withExplicitType() let generated = variable.generateCode().normalize() #expect(generated.contains("let lookup: [Int: String]")) @@ -92,7 +96,8 @@ internal struct VariableStaticTests { // MARK: - Static Method Tests @Test internal func testStaticMethodReturnsNewInstance() { - let original = Variable(.let, name: "test", type: "String", equals: "value") + let original = Variable(.let, name: "test", type: "String", equals: Literal.ref("value")) + .withExplicitType() let staticVersion = original.static() // Should be different instances @@ -108,7 +113,8 @@ internal struct VariableStaticTests { } @Test internal func testStaticMethodPreservesOtherProperties() { - let original = Variable(.var, name: "test", type: "String", equals: "value") + let original = Variable(.var, name: "test", type: "String", equals: Literal.ref("value")) + .withExplicitType() let staticVersion = original.static() let originalGenerated = original.generateCode().normalize() @@ -129,7 +135,7 @@ internal struct VariableStaticTests { @Test internal func testEmptyArrayLiteral() { let array: [String] = [] - let variable = Variable(.let, name: "empty", equals: array).static() + let variable = Variable(.let, name: "empty", equals: array).withExplicitType().static() let generated = variable.generateCode().normalize() #expect(generated.contains("static let empty: [String] = []")) @@ -137,14 +143,20 @@ internal struct VariableStaticTests { @Test internal func testEmptyDictionaryLiteral() { let dict: [Int: String] = [:] - let variable = Variable(.let, name: "empty", equals: dict).static() + let variable = Variable(.let, name: "empty", equals: dict).withExplicitType().static() let generated = variable.generateCode().normalize() - #expect(generated.contains("static let empty: [Int: String] = []")) + let validOutputs = [ + "static let empty: [Int: String] = [:]", + "static let empty: [Int: String] = [: ]", + ] + #expect(validOutputs.contains { generated.contains($0) }) } @Test internal func testMultipleStaticCalls() { - let variable = Variable(.let, name: "test", type: "String", equals: "value").static().static() + let variable = Variable(.let, name: "test", type: "String", equals: Literal.ref("value")) + .withExplicitType() + .static().static() let generated = variable.generateCode().normalize() // Should still only have one "static" keyword diff --git a/codecov.yml b/codecov.yml index 951b97b..621ea02 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,2 +1,3 @@ ignore: - "Tests" + - "Sources/SyntaxKit/parser" From c4af5ed11c4ac0507c9411e3215cbc64b8a79cbc Mon Sep 17 00:00:00 2001 From: leogdion Date: Sat, 21 Jun 2025 21:17:58 -0400 Subject: [PATCH 06/10] Adding Concurrency and Error Throws (#77) --- .swiftlint.yml | 4 + Examples/Completed/concurrency/code.swift | 42 +++ Examples/Completed/concurrency/dsl.swift | 48 ++++ Examples/Completed/concurrency/syntax.json | 1 + Examples/Completed/errors_async/code.swift | 23 ++ Examples/Completed/errors_async/dsl.swift | 74 +++++ Examples/Completed/errors_async/syntax.json | 1 + Examples/Remaining/concurrency/code.swift | 87 ------ Examples/Remaining/result_builders/code.swift | 58 ++++ Line.swift | 3 +- Sources/SyntaxKit/Assignment.swift | 3 +- Sources/SyntaxKit/Call.swift | 49 +++- Sources/SyntaxKit/Case.swift | 73 ++++- Sources/SyntaxKit/Catch.swift | 198 ++++++++++++++ Sources/SyntaxKit/CatchBuilder.swift | 62 +++++ Sources/SyntaxKit/CodeBlock+Generate.swift | 6 +- Sources/SyntaxKit/Default.swift | 3 +- Sources/SyntaxKit/DictionaryExpr.swift | 89 ++++++ Sources/SyntaxKit/DictionaryLiteral.swift | 2 +- Sources/SyntaxKit/DictionaryValue.swift | 72 +++++ Sources/SyntaxKit/Do.swift | 78 ++++++ Sources/SyntaxKit/EnumCase+Syntax.swift | 133 +++++++++ Sources/SyntaxKit/EnumCase.swift | 132 +++++---- .../SyntaxKit/Function+EffectSpecifiers.swift | 88 ++++++ Sources/SyntaxKit/Function+Effects.swift | 91 +++++++ Sources/SyntaxKit/Function+Modifiers.swift | 59 ++++ Sources/SyntaxKit/Function+Syntax.swift | 195 ++++++++++++++ Sources/SyntaxKit/Function.swift | 201 ++------------ Sources/SyntaxKit/Guard.swift | 14 +- Sources/SyntaxKit/If.swift | 20 +- Sources/SyntaxKit/Infix.swift | 50 ++++ Sources/SyntaxKit/Init.swift | 19 +- Sources/SyntaxKit/Line.swift | 21 ++ Sources/SyntaxKit/Literal+ExprCodeBlock.swift | 1 + Sources/SyntaxKit/Parameter.swift | 73 ++++- Sources/SyntaxKit/SwitchCase.swift | 3 +- Sources/SyntaxKit/Throw.swift | 57 ++++ Sources/SyntaxKit/Tuple.swift | 54 +++- .../SyntaxKit/TupleAssignment+AsyncSet.swift | 95 +++++++ Sources/SyntaxKit/TupleAssignment.swift | 207 ++++++++++++++ Sources/SyntaxKit/TupleLiteral.swift | 2 +- ...ift => Variable+LiteralInitializers.swift} | 116 +------- .../Variable+TypedInitializers.swift | 154 +++++++++++ Sources/SyntaxKit/Variable.swift | 57 +++- Sources/SyntaxKit/VariableDecl.swift | 6 +- Sources/SyntaxKit/VariableExp.swift | 63 ++++- .../parser/TokenVisitor+Helpers.swift | 84 ++++++ Sources/SyntaxKit/parser/TokenVisitor.swift | 55 +--- .../Integration/CommentTests.swift | 7 +- .../Integration/ConcurrencyExampleTests.swift | 157 +++++++++++ .../ConditionalsExampleTests.swift | 21 +- .../Integration/ForLoopsExampleTests.swift | 57 ++-- .../SyntaxKitTests/Unit/AttributeTests.swift | 4 +- .../SyntaxKitTests/Unit/CatchBasicTests.swift | 157 +++++++++++ .../Unit/CatchComplexTests.swift | 110 ++++++++ .../Unit/CatchEdgeCaseTests.swift | 113 ++++++++ .../Unit/CatchIntegrationTests.swift | 124 +++++++++ .../Unit/CodeStyleMigrationTests.swift | 3 +- Tests/SyntaxKitTests/Unit/DoBasicTests.swift | 91 +++++++ .../SyntaxKitTests/Unit/DoComplexTests.swift | 112 ++++++++ .../SyntaxKitTests/Unit/DoEdgeCaseTests.swift | 156 +++++++++++ .../Unit/DoIntegrationTests.swift | 88 ++++++ Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift | 253 ------------------ .../Unit/EdgeCaseTestsExpressions.swift | 129 +++++++++ .../Unit/EdgeCaseTestsTypes.swift | 136 ++++++++++ .../Unit/ErrorHandlingTests.swift | 129 +++++++++ .../Unit/MainApplicationTests.swift | 5 +- .../Unit/OptionsMacroIntegrationTests.swift | 42 +-- .../OptionsMacroIntegrationTestsAPI.swift | 39 +++ .../SyntaxKitTests/Unit/ThrowBasicTests.swift | 92 +++++++ .../Unit/ThrowComplexTests.swift | 131 +++++++++ .../Unit/ThrowEdgeCaseTests.swift | 37 +++ .../Unit/ThrowFunctionTests.swift | 66 +++++ .../Unit/TupleAssignmentAsyncTests.swift | 122 +++++++++ .../Unit/TupleAssignmentBasicTests.swift | 72 +++++ .../Unit/TupleAssignmentEdgeCaseTests.swift | 82 ++++++ .../TupleAssignmentIntegrationTests.swift | 96 +++++++ 77 files changed, 4787 insertions(+), 870 deletions(-) create mode 100644 Examples/Completed/concurrency/code.swift create mode 100644 Examples/Completed/concurrency/dsl.swift create mode 100644 Examples/Completed/concurrency/syntax.json create mode 100644 Examples/Completed/errors_async/code.swift create mode 100644 Examples/Completed/errors_async/dsl.swift create mode 100644 Examples/Completed/errors_async/syntax.json delete mode 100644 Examples/Remaining/concurrency/code.swift create mode 100644 Examples/Remaining/result_builders/code.swift create mode 100644 Sources/SyntaxKit/Catch.swift create mode 100644 Sources/SyntaxKit/CatchBuilder.swift create mode 100644 Sources/SyntaxKit/DictionaryExpr.swift create mode 100644 Sources/SyntaxKit/DictionaryValue.swift create mode 100644 Sources/SyntaxKit/Do.swift create mode 100644 Sources/SyntaxKit/EnumCase+Syntax.swift create mode 100644 Sources/SyntaxKit/Function+EffectSpecifiers.swift create mode 100644 Sources/SyntaxKit/Function+Effects.swift create mode 100644 Sources/SyntaxKit/Function+Modifiers.swift create mode 100644 Sources/SyntaxKit/Function+Syntax.swift create mode 100644 Sources/SyntaxKit/Throw.swift create mode 100644 Sources/SyntaxKit/TupleAssignment+AsyncSet.swift create mode 100644 Sources/SyntaxKit/TupleAssignment.swift rename Sources/SyntaxKit/{Variable+Initializers.swift => Variable+LiteralInitializers.swift} (60%) create mode 100644 Sources/SyntaxKit/Variable+TypedInitializers.swift create mode 100644 Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift create mode 100644 Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/CatchBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/CatchComplexTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/CatchEdgeCaseTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/CatchIntegrationTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/DoBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/DoComplexTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/DoEdgeCaseTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/DoIntegrationTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/EdgeCaseTestsExpressions.swift create mode 100644 Tests/SyntaxKitTests/Unit/EdgeCaseTestsTypes.swift create mode 100644 Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTestsAPI.swift create mode 100644 Tests/SyntaxKitTests/Unit/ThrowBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/ThrowEdgeCaseTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/ThrowFunctionTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/TupleAssignmentBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/TupleAssignmentEdgeCaseTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/TupleAssignmentIntegrationTests.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 8481cde..91eed35 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -111,6 +111,10 @@ identifier_name: excluded: - id - no +type_name: + excluded: + - If + - Do excluded: - DerivedData - .build diff --git a/Examples/Completed/concurrency/code.swift b/Examples/Completed/concurrency/code.swift new file mode 100644 index 0000000..1be74cb --- /dev/null +++ b/Examples/Completed/concurrency/code.swift @@ -0,0 +1,42 @@ +enum VendingMachineError: Error { + case invalidSelection + case insufficientFunds(coinsNeeded: Int) + case outOfStock +} + +class VendingMachine { + var inventory = [ + "Candy Bar": Item(price: 12, count: 7), + "Chips": Item(price: 10, count: 4), + "Pretzels": Item(price: 7, count: 11) + ] + var coinsDeposited = 0 + + + func vend(itemNamed name: String) throws { + guard let item = inventory[name] else { + throw VendingMachineError.invalidSelection + } + + + guard item.count > 0 else { + throw VendingMachineError.outOfStock + } + + + guard item.price <= coinsDeposited else { + throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited) + } + + + coinsDeposited -= item.price + + + var newItem = item + newItem.count -= 1 + inventory[name] = newItem + + + print("Dispensing \(name)") + } +} \ No newline at end of file diff --git a/Examples/Completed/concurrency/dsl.swift b/Examples/Completed/concurrency/dsl.swift new file mode 100644 index 0000000..300a460 --- /dev/null +++ b/Examples/Completed/concurrency/dsl.swift @@ -0,0 +1,48 @@ +Enum("VendingMachineError") { + Case("invalidSelection") + Case("insufficientFunds").associatedValue("coinsNeeded", type: "Int") + Case("outOfStock") +} + +Class("VendingMachine") { + Variable(.var, name: "inventory", equals: Literal.dictionary(Dictionary(uniqueKeysWithValues: [ + ("Candy Bar", Item(price: 12, count: 7)), + ("Chips", Item(price: 10, count: 4)), + ("Pretzels", Item(price: 7, count: 11)) + ]))) + Variable(.var, name: "coinsDeposited", equals: 0) + + Function("vend"){ + Parameter("name", labeled: "itemNamed", type: "String") + } _: { + Guard("let item = inventory[itemNamed]") else: { + Throw( + EnumValue("VendingMachineError", case: "invalidSelection") + ) + } + Guard("item.count > 0") else: { + Throw( + EnumValue("VendingMachineError", case: "outOfStock") + ) + } + Guard("item.price <= coinsDeposited") else: { + Throw( + EnumValue("VendingMachineError", case: "insufficientFunds"){ + ParameterExp("coinsNeeded", value: Infix("-"){ + VariableExp("item").property("price") + VariableExp("coinsDeposited") + }) + } + ) + } + Infix("-=", "coinsDeposited", VariableExp("item").property("price")) + Variable("newItem", equals: VariableExp("item")) + Infix("-=", "newItem.count", 1) + Assignment("inventory[itemNamed]", .ref("newItem")) + Call("print", "Dispensing \\(itemNamed)") + } +} + + + + diff --git a/Examples/Completed/concurrency/syntax.json b/Examples/Completed/concurrency/syntax.json new file mode 100644 index 0000000..b514de5 --- /dev/null +++ b/Examples/Completed/concurrency/syntax.json @@ -0,0 +1 @@ +[{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeShebang"},{"value":{"text":"nil"},"name":"shebang"},{"value":{"text":"nil"},"name":"unexpectedBetweenShebangAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndEndOfFileToken"},{"value":{"text":"","kind":"endOfFile"},"name":"endOfFileToken"},{"value":{"text":"nil"},"name":"unexpectedAfterEndOfFileToken"}],"text":"SourceFile","type":"other","id":0,"range":{"endRow":42,"endColumn":2,"startRow":1,"startColumn":1}},{"id":1,"type":"collection","text":"CodeBlockItemList","parent":0,"range":{"endRow":42,"startRow":1,"startColumn":1,"endColumn":2},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}]},{"id":2,"type":"other","text":"CodeBlockItem","parent":1,"range":{"startColumn":1,"endRow":5,"startRow":1,"endColumn":2},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"EnumDeclSyntax"},"ref":"EnumDeclSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"id":3,"type":"decl","text":"EnumDecl","parent":2,"range":{"startRow":1,"endColumn":2,"startColumn":1,"endRow":5},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndEnumKeyword","value":{"text":"nil"}},{"name":"enumKeyword","value":{"text":"enum","kind":"keyword(SwiftSyntax.Keyword.enum)"}},{"name":"unexpectedBetweenEnumKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"VendingMachineError","kind":"identifier("VendingMachineError")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndInheritanceClause","value":{"text":"nil"}},{"ref":"InheritanceClauseSyntax","name":"inheritanceClause","value":{"text":"InheritanceClauseSyntax"}},{"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock","value":{"text":"nil"}},{"ref":"MemberBlockSyntax","name":"memberBlock","value":{"text":"MemberBlockSyntax"}},{"name":"unexpectedAfterMemberBlock","value":{"text":"nil"}}]},{"structure":[{"name":"Element","value":{"text":"Element"}},{"value":{"text":"0"},"name":"Count"}],"type":"collection","parent":3,"id":4,"text":"AttributeList","range":{"startRow":1,"startColumn":1,"endColumn":1,"endRow":1}},{"text":"DeclModifierList","range":{"startRow":1,"endRow":1,"endColumn":1,"startColumn":1},"id":5,"parent":3,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection"},{"id":6,"type":"other","text":"enum","range":{"startColumn":1,"endRow":1,"startRow":1,"endColumn":5},"token":{"kind":"keyword(SwiftSyntax.Keyword.enum)","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"parent":3},{"parent":3,"structure":[],"type":"other","range":{"startColumn":6,"endRow":1,"startRow":1,"endColumn":25},"text":"VendingMachineError","id":7,"token":{"kind":"identifier("VendingMachineError")","trailingTrivia":"","leadingTrivia":""}},{"text":"InheritanceClause","range":{"startColumn":25,"endRow":1,"startRow":1,"endColumn":32},"id":8,"parent":3,"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndInheritedTypes","value":{"text":"nil"}},{"ref":"InheritedTypeListSyntax","name":"inheritedTypes","value":{"text":"InheritedTypeListSyntax"}},{"name":"unexpectedAfterInheritedTypes","value":{"text":"nil"}}],"type":"other"},{"type":"other","text":":","range":{"endRow":1,"endColumn":26,"startColumn":25,"startRow":1},"id":9,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"colon"},"structure":[],"parent":8},{"text":"InheritedTypeList","range":{"endRow":1,"endColumn":32,"startColumn":27,"startRow":1},"id":10,"parent":8,"structure":[{"name":"Element","value":{"text":"InheritedTypeSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"text":"InheritedType","range":{"startColumn":27,"startRow":1,"endRow":1,"endColumn":32},"id":11,"parent":10,"structure":[{"name":"unexpectedBeforeType","value":{"text":"nil"}},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"text":"IdentifierType","parent":11,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"Error","kind":"identifier("Error")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"range":{"endColumn":32,"startColumn":27,"startRow":1,"endRow":1},"id":12,"type":"type"},{"text":"Error","parent":12,"structure":[],"token":{"kind":"identifier("Error")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"startRow":1,"endRow":1,"endColumn":32,"startColumn":27},"type":"other","id":13},{"text":"MemberBlock","parent":3,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"name":"members","ref":"MemberBlockItemListSyntax","value":{"text":"MemberBlockItemListSyntax"}},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"range":{"startRow":1,"endRow":5,"endColumn":2,"startColumn":33},"id":14,"type":"other"},{"type":"other","text":"{","id":15,"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"startColumn":33,"startRow":1,"endRow":1,"endColumn":34},"parent":14},{"structure":[{"value":{"text":"MemberBlockItemSyntax"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"parent":14,"type":"collection","range":{"startColumn":5,"startRow":2,"endRow":4,"endColumn":20},"text":"MemberBlockItemList","id":16},{"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"EnumCaseDeclSyntax","value":{"text":"EnumCaseDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":16,"type":"other","range":{"endColumn":26,"startColumn":5,"startRow":2,"endRow":2},"text":"MemberBlockItem","id":17},{"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"EnumCaseElementListSyntax"},"ref":"EnumCaseElementListSyntax"},{"name":"unexpectedAfterElements","value":{"text":"nil"}}],"parent":17,"type":"decl","range":{"startRow":2,"endRow":2,"endColumn":26,"startColumn":5},"text":"EnumCaseDecl","id":18},{"id":19,"range":{"endRow":1,"endColumn":34,"startRow":1,"startColumn":34},"text":"AttributeList","type":"collection","parent":18,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}]},{"id":20,"range":{"startRow":1,"startColumn":34,"endRow":1,"endColumn":34},"text":"DeclModifierList","type":"collection","parent":18,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"parent":18,"id":21,"range":{"startColumn":5,"startRow":2,"endRow":2,"endColumn":9},"structure":[],"text":"case","token":{"kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"type":"other"},{"id":22,"range":{"startColumn":10,"startRow":2,"endRow":2,"endColumn":26},"text":"EnumCaseElementList","type":"collection","parent":18,"structure":[{"value":{"text":"EnumCaseElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"id":23,"range":{"startRow":2,"endColumn":26,"startColumn":10,"endRow":2},"text":"EnumCaseElement","type":"other","parent":22,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"invalidSelection","kind":"identifier("invalidSelection")"}},{"name":"unexpectedBetweenNameAndParameterClause","value":{"text":"nil"}},{"name":"parameterClause","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenParameterClauseAndRawValue"},{"value":{"text":"nil"},"name":"rawValue"},{"value":{"text":"nil"},"name":"unexpectedBetweenRawValueAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"parent":23,"structure":[],"id":24,"range":{"startColumn":10,"endRow":2,"endColumn":26,"startRow":2},"text":"invalidSelection","token":{"kind":"identifier("invalidSelection")","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"parent":16,"text":"MemberBlockItem","structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","value":{"text":"EnumCaseDeclSyntax"},"ref":"EnumCaseDeclSyntax"},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","id":25,"range":{"startColumn":5,"endRow":3,"endColumn":45,"startRow":3}},{"parent":25,"text":"EnumCaseDecl","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"name":"attributes","ref":"AttributeListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"name":"modifiers","ref":"DeclModifierListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndCaseKeyword"},{"value":{"text":"case","kind":"keyword(SwiftSyntax.Keyword.case)"},"name":"caseKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCaseKeywordAndElements"},{"value":{"text":"EnumCaseElementListSyntax"},"ref":"EnumCaseElementListSyntax","name":"elements"},{"value":{"text":"nil"},"name":"unexpectedAfterElements"}],"type":"decl","id":26,"range":{"startRow":3,"startColumn":5,"endRow":3,"endColumn":45}},{"id":27,"parent":26,"range":{"startColumn":26,"endRow":2,"endColumn":26,"startRow":2},"text":"AttributeList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection"},{"id":28,"parent":26,"range":{"endRow":2,"startRow":2,"startColumn":26,"endColumn":26},"text":"DeclModifierList","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection"},{"parent":26,"id":29,"range":{"startRow":3,"startColumn":5,"endRow":3,"endColumn":9},"structure":[],"text":"case","token":{"kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"type":"other"},{"id":30,"parent":26,"range":{"startRow":3,"startColumn":10,"endRow":3,"endColumn":45},"text":"EnumCaseElementList","structure":[{"name":"Element","value":{"text":"EnumCaseElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"id":31,"parent":30,"range":{"endColumn":45,"endRow":3,"startColumn":10,"startRow":3},"text":"EnumCaseElement","structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"insufficientFunds","kind":"identifier("insufficientFunds")"}},{"name":"unexpectedBetweenNameAndParameterClause","value":{"text":"nil"}},{"value":{"text":"EnumCaseParameterClauseSyntax"},"ref":"EnumCaseParameterClauseSyntax","name":"parameterClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenParameterClauseAndRawValue"},{"value":{"text":"nil"},"name":"rawValue"},{"value":{"text":"nil"},"name":"unexpectedBetweenRawValueAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"parent":31,"id":32,"range":{"startRow":3,"endColumn":27,"endRow":3,"startColumn":10},"structure":[],"text":"insufficientFunds","token":{"kind":"identifier("insufficientFunds")","leadingTrivia":"","trailingTrivia":""},"type":"other"},{"text":"EnumCaseParameterClause","range":{"startRow":3,"endColumn":45,"endRow":3,"startColumn":27},"id":33,"parent":31,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndParameters"},{"value":{"text":"EnumCaseParameterListSyntax"},"name":"parameters","ref":"EnumCaseParameterListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenParametersAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"type":"other"},{"parent":33,"id":34,"range":{"startColumn":27,"startRow":3,"endRow":3,"endColumn":28},"structure":[],"text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"type":"other"},{"parent":33,"type":"collection","id":35,"text":"EnumCaseParameterList","range":{"endRow":3,"endColumn":44,"startRow":3,"startColumn":28},"structure":[{"name":"Element","value":{"text":"EnumCaseParameterSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"structure":[{"name":"unexpectedBeforeModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFirstName","value":{"text":"nil"}},{"name":"firstName","value":{"text":"coinsNeeded","kind":"identifier("coinsNeeded")"}},{"name":"unexpectedBetweenFirstNameAndSecondName","value":{"text":"nil"}},{"name":"secondName","value":{"text":"nil"}},{"name":"unexpectedBetweenSecondNameAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenTypeAndDefaultValue","value":{"text":"nil"}},{"name":"defaultValue","value":{"text":"nil"}},{"name":"unexpectedBetweenDefaultValueAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","id":36,"text":"EnumCaseParameter","range":{"endColumn":44,"startColumn":28,"startRow":3,"endRow":3},"parent":35},{"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","id":37,"text":"DeclModifierList","range":{"endColumn":28,"startColumn":28,"startRow":3,"endRow":3},"parent":36},{"parent":36,"id":38,"range":{"startColumn":28,"startRow":3,"endRow":3,"endColumn":39},"structure":[],"text":"coinsNeeded","token":{"kind":"identifier("coinsNeeded")","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"parent":36,"id":39,"range":{"startColumn":39,"startRow":3,"endRow":3,"endColumn":40},"structure":[],"text":":","token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""},"type":"other"},{"parent":36,"text":"IdentifierType","range":{"startColumn":41,"startRow":3,"endRow":3,"endColumn":44},"id":40,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("Int")","text":"Int"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"type":"type"},{"parent":40,"id":41,"range":{"endRow":3,"endColumn":44,"startColumn":41,"startRow":3},"structure":[],"text":"Int","token":{"leadingTrivia":"","kind":"identifier("Int")","trailingTrivia":""},"type":"other"},{"parent":33,"id":42,"range":{"endRow":3,"endColumn":45,"startColumn":44,"startRow":3},"structure":[],"text":")","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"type":"other"},{"parent":16,"text":"MemberBlockItem","range":{"endRow":4,"endColumn":20,"startColumn":5,"startRow":4},"id":43,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"EnumCaseDeclSyntax"},"name":"decl","ref":"EnumCaseDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other"},{"parent":43,"id":44,"range":{"startColumn":5,"endColumn":20,"startRow":4,"endRow":4},"type":"decl","text":"EnumCaseDecl","structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndCaseKeyword","value":{"text":"nil"}},{"name":"caseKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.case)","text":"case"}},{"name":"unexpectedBetweenCaseKeywordAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"EnumCaseElementListSyntax"},"ref":"EnumCaseElementListSyntax"},{"name":"unexpectedAfterElements","value":{"text":"nil"}}]},{"parent":44,"id":45,"range":{"startColumn":45,"endRow":3,"endColumn":45,"startRow":3},"type":"collection","text":"AttributeList","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"parent":44,"id":46,"range":{"startRow":3,"endRow":3,"startColumn":45,"endColumn":45},"type":"collection","text":"DeclModifierList","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"parent":44,"id":47,"range":{"startRow":4,"startColumn":5,"endColumn":9,"endRow":4},"structure":[],"text":"case","token":{"kind":"keyword(SwiftSyntax.Keyword.case)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"type":"other"},{"type":"collection","range":{"endRow":4,"startColumn":10,"endColumn":20,"startRow":4},"text":"EnumCaseElementList","structure":[{"value":{"text":"EnumCaseElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":44,"id":48},{"type":"other","range":{"startRow":4,"endRow":4,"endColumn":20,"startColumn":10},"text":"EnumCaseElement","structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("outOfStock")","text":"outOfStock"}},{"name":"unexpectedBetweenNameAndParameterClause","value":{"text":"nil"}},{"name":"parameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenParameterClauseAndRawValue","value":{"text":"nil"}},{"name":"rawValue","value":{"text":"nil"}},{"name":"unexpectedBetweenRawValueAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":48,"id":49},{"parent":49,"structure":[],"range":{"endColumn":20,"startColumn":10,"startRow":4,"endRow":4},"id":50,"text":"outOfStock","token":{"trailingTrivia":"","kind":"identifier("outOfStock")","leadingTrivia":""},"type":"other"},{"parent":14,"structure":[],"range":{"endColumn":2,"startColumn":1,"startRow":5,"endRow":5},"id":51,"text":"}","token":{"trailingTrivia":"","kind":"rightBrace","leadingTrivia":"↲<\/span>"},"type":"other"},{"type":"other","range":{"endColumn":2,"startColumn":1,"startRow":7,"endRow":42},"text":"CodeBlockItem","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"ClassDeclSyntax","name":"item","value":{"text":"ClassDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":1,"id":52},{"type":"decl","parent":52,"text":"ClassDecl","range":{"endRow":42,"startRow":7,"startColumn":1,"endColumn":2},"id":53,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndClassKeyword","value":{"text":"nil"}},{"name":"classKeyword","value":{"text":"class","kind":"keyword(SwiftSyntax.Keyword.class)"}},{"name":"unexpectedBetweenClassKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"text":"VendingMachine","kind":"identifier("VendingMachine")"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndInheritanceClause","value":{"text":"nil"}},{"name":"inheritanceClause","value":{"text":"nil"}},{"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock","value":{"text":"nil"}},{"value":{"text":"MemberBlockSyntax"},"ref":"MemberBlockSyntax","name":"memberBlock"},{"value":{"text":"nil"},"name":"unexpectedAfterMemberBlock"}]},{"text":"AttributeList","range":{"startRow":5,"startColumn":2,"endRow":5,"endColumn":2},"type":"collection","id":54,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"parent":53},{"text":"DeclModifierList","range":{"startColumn":2,"endColumn":2,"startRow":5,"endRow":5},"type":"collection","id":55,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":53},{"parent":53,"id":56,"range":{"startRow":7,"startColumn":1,"endRow":7,"endColumn":6},"structure":[],"text":"class","token":{"kind":"keyword(SwiftSyntax.Keyword.class)","leadingTrivia":"↲<\/span>↲<\/span>","trailingTrivia":"␣<\/span>"},"type":"other"},{"parent":53,"id":57,"range":{"startRow":7,"startColumn":7,"endRow":7,"endColumn":21},"structure":[],"text":"VendingMachine","token":{"kind":"identifier("VendingMachine")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"type":"other"},{"text":"MemberBlock","range":{"startRow":7,"startColumn":22,"endRow":42,"endColumn":2},"type":"other","id":58,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"name":"members","value":{"text":"MemberBlockItemListSyntax"},"ref":"MemberBlockItemListSyntax"},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"parent":53},{"parent":58,"id":59,"structure":[],"range":{"startRow":7,"endRow":7,"endColumn":23,"startColumn":22},"text":"{","token":{"leadingTrivia":"","kind":"leftBrace","trailingTrivia":""},"type":"other"},{"id":60,"parent":58,"type":"collection","structure":[{"name":"Element","value":{"text":"MemberBlockItemSyntax"}},{"name":"Count","value":{"text":"3"}}],"range":{"startRow":8,"endRow":41,"endColumn":6,"startColumn":5},"text":"MemberBlockItemList"},{"id":61,"parent":60,"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"VariableDeclSyntax"},"name":"decl","ref":"VariableDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"range":{"startRow":8,"endRow":12,"endColumn":6,"startColumn":5},"text":"MemberBlockItem"},{"id":62,"parent":61,"type":"decl","structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.var)","text":"var"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"range":{"startRow":8,"endColumn":6,"endRow":12,"startColumn":5},"text":"VariableDecl"},{"id":63,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","parent":62,"text":"AttributeList","range":{"startRow":7,"endRow":7,"endColumn":23,"startColumn":23}},{"id":64,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}],"type":"collection","parent":62,"text":"DeclModifierList","range":{"startRow":7,"endRow":7,"endColumn":23,"startColumn":23}},{"parent":62,"id":65,"structure":[],"range":{"endColumn":8,"startRow":8,"startColumn":5,"endRow":8},"text":"var","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)","trailingTrivia":"␣<\/span>"},"type":"other"},{"id":66,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":62,"text":"PatternBindingList","range":{"endColumn":6,"startRow":8,"startColumn":9,"endRow":12}},{"id":67,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":66,"text":"PatternBinding","range":{"startColumn":9,"endRow":12,"startRow":8,"endColumn":6}},{"text":"IdentifierPattern","range":{"startRow":8,"startColumn":9,"endRow":8,"endColumn":18},"type":"pattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"inventory","kind":"identifier("inventory")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"id":68,"parent":67},{"parent":68,"structure":[],"range":{"startColumn":9,"endRow":8,"startRow":8,"endColumn":18},"id":69,"text":"inventory","token":{"leadingTrivia":"","kind":"identifier("inventory")","trailingTrivia":"␣<\/span>"},"type":"other"},{"text":"InitializerClause","range":{"startColumn":19,"endRow":12,"startRow":8,"endColumn":6},"type":"other","structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"DictionaryExprSyntax","name":"value","value":{"text":"DictionaryExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}],"id":70,"parent":67},{"parent":70,"structure":[],"range":{"startRow":8,"endRow":8,"endColumn":20,"startColumn":19},"id":71,"text":"=","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"},"type":"other"},{"text":"DictionaryExpr","range":{"endRow":12,"startRow":8,"endColumn":6,"startColumn":21},"structure":[{"name":"unexpectedBeforeLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"text":"[","kind":"leftSquare"}},{"name":"unexpectedBetweenLeftSquareAndContent","value":{"text":"nil"}},{"name":"content","ref":"DictionaryElementListSyntax","value":{"text":"DictionaryElementListSyntax"}},{"name":"unexpectedBetweenContentAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedAfterRightSquare","value":{"text":"nil"}}],"type":"expr","id":72,"parent":70},{"parent":72,"structure":[],"range":{"endRow":8,"startColumn":21,"endColumn":22,"startRow":8},"id":73,"text":"[","token":{"kind":"leftSquare","trailingTrivia":"","leadingTrivia":""},"type":"other"},{"text":"DictionaryElementList","range":{"endRow":11,"startColumn":9,"endColumn":46,"startRow":9},"structure":[{"name":"Element","value":{"text":"DictionaryElementSyntax"}},{"name":"Count","value":{"text":"3"}}],"type":"collection","id":74,"parent":72},{"text":"DictionaryElement","range":{"startColumn":9,"startRow":9,"endRow":9,"endColumn":48},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeKey"},{"value":{"text":"StringLiteralExprSyntax"},"name":"key","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenKeyAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndValue"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"value"},{"value":{"text":"nil"},"name":"unexpectedBetweenValueAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","id":75,"parent":74},{"range":{"endColumn":20,"startRow":9,"startColumn":9,"endRow":9},"id":76,"parent":75,"text":"StringLiteralExpr","type":"expr","structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}]},{"parent":76,"id":77,"range":{"startRow":9,"endRow":9,"endColumn":10,"startColumn":9},"structure":[],"text":""","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"stringQuote"},"type":"other"},{"type":"collection","text":"StringLiteralSegmentList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"parent":76,"id":78,"range":{"startRow":9,"startColumn":10,"endRow":9,"endColumn":19}},{"type":"other","text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Candy Bar","kind":"stringSegment("Candy Bar")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"parent":78,"id":79,"range":{"startColumn":10,"endColumn":19,"endRow":9,"startRow":9}},{"parent":79,"structure":[],"id":80,"range":{"endRow":9,"startColumn":10,"startRow":9,"endColumn":19},"text":"Candy␣<\/span>Bar","token":{"leadingTrivia":"","kind":"stringSegment("Candy Bar")","trailingTrivia":""},"type":"other"},{"type":"other","text":""","range":{"endRow":9,"startColumn":19,"startRow":9,"endColumn":20},"id":81,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"structure":[],"parent":76},{"type":"other","text":":","range":{"endRow":9,"startColumn":20,"startRow":9,"endColumn":21},"id":82,"token":{"leadingTrivia":"","kind":"colon","trailingTrivia":"␣<\/span>"},"structure":[],"parent":75},{"type":"expr","text":"FunctionCallExpr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"parent":75,"id":83,"range":{"endRow":9,"startColumn":22,"startRow":9,"endColumn":47}},{"range":{"endRow":9,"startRow":9,"startColumn":22,"endColumn":26},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"Item","kind":"identifier("Item")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":83,"id":84,"text":"DeclReferenceExpr"},{"type":"other","text":"Item","range":{"startColumn":22,"endRow":9,"endColumn":26,"startRow":9},"id":85,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("Item")"},"structure":[],"parent":84},{"type":"other","text":"(","range":{"startColumn":26,"endRow":9,"endColumn":27,"startRow":9},"id":86,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"structure":[],"parent":83},{"range":{"startColumn":27,"endRow":9,"endColumn":46,"startRow":9},"type":"collection","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"parent":83,"id":87,"text":"LabeledExprList"},{"range":{"endRow":9,"startColumn":27,"endColumn":37,"startRow":9},"type":"other","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"price","kind":"identifier("price")"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"kind":"comma","text":","}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":87,"id":88,"text":"LabeledExpr"},{"type":"other","text":"price","range":{"endRow":9,"startRow":9,"endColumn":32,"startColumn":27},"id":89,"token":{"kind":"identifier("price")","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":88},{"type":"other","text":":","range":{"endRow":9,"startRow":9,"endColumn":33,"startColumn":32},"id":90,"token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"parent":88},{"id":91,"range":{"endRow":9,"startRow":9,"endColumn":36,"startColumn":34},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("12")","text":"12"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","text":"IntegerLiteralExpr","parent":88},{"type":"other","text":"12","range":{"startColumn":34,"endRow":9,"endColumn":36,"startRow":9},"id":92,"token":{"kind":"integerLiteral("12")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":91},{"type":"other","text":",","range":{"startColumn":36,"endRow":9,"endColumn":37,"startRow":9},"id":93,"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"parent":88},{"id":94,"range":{"startColumn":38,"endRow":9,"endColumn":46,"startRow":9},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"count","kind":"identifier("count")"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"LabeledExpr","parent":87},{"type":"other","text":"count","range":{"startRow":9,"endColumn":43,"startColumn":38,"endRow":9},"id":95,"token":{"kind":"identifier("count")","trailingTrivia":"","leadingTrivia":""},"structure":[],"parent":94},{"type":"other","text":":","range":{"startRow":9,"endColumn":44,"startColumn":43,"endRow":9},"id":96,"token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"parent":94},{"type":"expr","structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"7","kind":"integerLiteral("7")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"id":97,"text":"IntegerLiteralExpr","parent":94,"range":{"startRow":9,"endColumn":46,"startColumn":45,"endRow":9}},{"type":"other","text":"7","range":{"startRow":9,"startColumn":45,"endColumn":46,"endRow":9},"id":98,"token":{"leadingTrivia":"","kind":"integerLiteral("7")","trailingTrivia":""},"structure":[],"parent":97},{"type":"other","text":")","range":{"startRow":9,"startColumn":46,"endColumn":47,"endRow":9},"id":99,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"structure":[],"parent":83},{"type":"collection","structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"value":{"text":"0"},"name":"Count"}],"parent":83,"text":"MultipleTrailingClosureElementList","range":{"startColumn":47,"endColumn":47,"startRow":9,"endRow":9},"id":100},{"type":"other","text":",","range":{"endRow":9,"startColumn":47,"startRow":9,"endColumn":48},"id":101,"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":75},{"type":"other","structure":[{"name":"unexpectedBeforeKey","value":{"text":"nil"}},{"name":"key","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenKeyAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndValue","value":{"text":"nil"}},{"name":"value","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenValueAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":74,"range":{"endRow":10,"startColumn":9,"startRow":10,"endColumn":44},"text":"DictionaryElement","id":102},{"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"parent":102,"range":{"startRow":10,"startColumn":9,"endColumn":16,"endRow":10},"text":"StringLiteralExpr","id":103},{"text":""","type":"other","range":{"startColumn":9,"startRow":10,"endRow":10,"endColumn":10},"id":104,"token":{"kind":"stringQuote","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"structure":[],"parent":103},{"range":{"startColumn":10,"startRow":10,"endRow":10,"endColumn":15},"id":105,"parent":103,"text":"StringLiteralSegmentList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"range":{"startRow":10,"endRow":10,"endColumn":15,"startColumn":10},"id":106,"parent":105,"text":"StringSegment","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":"Chips","kind":"stringSegment("Chips")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other"},{"text":"Chips","type":"other","range":{"endColumn":15,"endRow":10,"startColumn":10,"startRow":10},"id":107,"token":{"trailingTrivia":"","kind":"stringSegment("Chips")","leadingTrivia":""},"structure":[],"parent":106},{"text":""","type":"other","range":{"endColumn":16,"endRow":10,"startColumn":15,"startRow":10},"id":108,"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"structure":[],"parent":103},{"text":":","type":"other","range":{"endRow":10,"startColumn":16,"startRow":10,"endColumn":17},"id":109,"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"parent":102},{"parent":102,"id":110,"range":{"startRow":10,"startColumn":18,"endColumn":43,"endRow":10},"text":"FunctionCallExpr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr"},{"parent":110,"id":111,"range":{"startRow":10,"endColumn":22,"endRow":10,"startColumn":18},"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("Item")","text":"Item"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"type":"other","text":"Item","range":{"endColumn":22,"startColumn":18,"endRow":10,"startRow":10},"id":112,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("Item")"},"structure":[],"parent":111},{"type":"other","text":"(","range":{"endColumn":23,"startColumn":22,"endRow":10,"startRow":10},"id":113,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"structure":[],"parent":110},{"type":"collection","text":"LabeledExprList","id":114,"parent":110,"range":{"endColumn":42,"startColumn":23,"endRow":10,"startRow":10},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}]},{"type":"other","text":"LabeledExpr","id":115,"parent":114,"range":{"startColumn":23,"endColumn":33,"endRow":10,"startRow":10},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"price","kind":"identifier("price")"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"kind":"comma","text":","}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"type":"other","text":"price","range":{"endColumn":28,"startRow":10,"startColumn":23,"endRow":10},"id":116,"token":{"kind":"identifier("price")","leadingTrivia":"","trailingTrivia":""},"structure":[],"parent":115},{"text":":","type":"other","range":{"endRow":10,"startRow":10,"startColumn":28,"endColumn":29},"id":117,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"structure":[],"parent":115},{"parent":115,"text":"IntegerLiteralExpr","range":{"endRow":10,"startRow":10,"startColumn":30,"endColumn":32},"id":118,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"10","kind":"integerLiteral("10")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"type":"expr"},{"type":"other","range":{"startRow":10,"endRow":10,"startColumn":30,"endColumn":32},"structure":[],"id":119,"text":"10","parent":118,"token":{"kind":"integerLiteral("10")","leadingTrivia":"","trailingTrivia":""}},{"type":"other","range":{"startRow":10,"endRow":10,"startColumn":32,"endColumn":33},"structure":[],"id":120,"text":",","parent":115,"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"parent":114,"text":"LabeledExpr","range":{"startRow":10,"endRow":10,"startColumn":34,"endColumn":42},"id":121,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"count","kind":"identifier("count")"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"type":"other","range":{"endRow":10,"endColumn":39,"startColumn":34,"startRow":10},"structure":[],"id":122,"text":"count","parent":121,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("count")"}},{"type":"other","range":{"endRow":10,"endColumn":40,"startColumn":39,"startRow":10},"structure":[],"id":123,"text":":","parent":121,"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"text":"IntegerLiteralExpr","id":124,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"4","kind":"integerLiteral("4")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"endRow":10,"endColumn":42,"startColumn":41,"startRow":10},"parent":121,"type":"expr"},{"type":"other","range":{"endColumn":42,"startColumn":41,"endRow":10,"startRow":10},"structure":[],"id":125,"text":"4","parent":124,"token":{"kind":"integerLiteral("4")","leadingTrivia":"","trailingTrivia":""}},{"type":"other","range":{"endColumn":43,"startColumn":42,"endRow":10,"startRow":10},"structure":[],"id":126,"text":")","parent":110,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""}},{"text":"MultipleTrailingClosureElementList","id":127,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"range":{"endColumn":43,"startColumn":43,"endRow":10,"startRow":10},"parent":110,"type":"collection"},{"type":"other","range":{"endRow":10,"endColumn":44,"startRow":10,"startColumn":43},"structure":[],"id":128,"text":",","parent":102,"token":{"leadingTrivia":"","kind":"comma","trailingTrivia":""}},{"text":"DictionaryElement","id":129,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeKey"},{"value":{"text":"StringLiteralExprSyntax"},"name":"key","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenKeyAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndValue"},{"value":{"text":"FunctionCallExprSyntax"},"name":"value","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenValueAndTrailingComma"},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endRow":11,"endColumn":46,"startRow":11,"startColumn":9},"parent":74,"type":"other"},{"range":{"startColumn":9,"endRow":11,"endColumn":19,"startRow":11},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax"},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":130,"text":"StringLiteralExpr","type":"expr","parent":129},{"type":"other","range":{"endRow":11,"startColumn":9,"startRow":11,"endColumn":10},"structure":[],"id":131,"text":""","parent":130,"token":{"kind":"stringQuote","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""}},{"range":{"endRow":11,"startColumn":10,"startRow":11,"endColumn":18},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"id":132,"text":"StringLiteralSegmentList","type":"collection","parent":130},{"id":133,"text":"StringSegment","structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("Pretzels")","text":"Pretzels"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","range":{"startRow":11,"startColumn":10,"endRow":11,"endColumn":18},"parent":132},{"type":"other","range":{"startRow":11,"startColumn":10,"endRow":11,"endColumn":18},"structure":[],"id":134,"text":"Pretzels","parent":133,"token":{"trailingTrivia":"","kind":"stringSegment("Pretzels")","leadingTrivia":""}},{"type":"other","range":{"startRow":11,"startColumn":18,"endRow":11,"endColumn":19},"structure":[],"id":135,"text":""","parent":130,"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""}},{"type":"other","range":{"startRow":11,"startColumn":19,"endRow":11,"endColumn":20},"structure":[],"id":136,"text":":","parent":129,"token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""}},{"id":137,"text":"FunctionCallExpr","structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","range":{"startRow":11,"startColumn":21,"endRow":11,"endColumn":46},"parent":129},{"parent":137,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"Item","kind":"identifier("Item")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","range":{"endRow":11,"endColumn":25,"startRow":11,"startColumn":21},"id":138,"text":"DeclReferenceExpr"},{"type":"other","range":{"startRow":11,"endColumn":25,"endRow":11,"startColumn":21},"structure":[],"id":139,"text":"Item","parent":138,"token":{"kind":"identifier("Item")","leadingTrivia":"","trailingTrivia":""}},{"type":"other","range":{"startRow":11,"endColumn":26,"endRow":11,"startColumn":25},"structure":[],"id":140,"text":"(","parent":137,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""}},{"parent":137,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"type":"collection","range":{"startRow":11,"endColumn":45,"endRow":11,"startColumn":26},"id":141,"text":"LabeledExprList"},{"parent":141,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"kind":"identifier("price")","text":"price"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":",","kind":"comma"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","range":{"startColumn":26,"endColumn":35,"startRow":11,"endRow":11},"id":142,"text":"LabeledExpr"},{"type":"other","range":{"endColumn":31,"startRow":11,"startColumn":26,"endRow":11},"structure":[],"id":143,"text":"price","parent":142,"token":{"trailingTrivia":"","kind":"identifier("price")","leadingTrivia":""}},{"type":"other","range":{"endColumn":32,"startRow":11,"startColumn":31,"endRow":11},"structure":[],"id":144,"text":":","parent":142,"token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"7","kind":"integerLiteral("7")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}],"id":145,"type":"expr","text":"IntegerLiteralExpr","range":{"endColumn":34,"startRow":11,"startColumn":33,"endRow":11},"parent":142},{"type":"other","range":{"endRow":11,"startColumn":33,"endColumn":34,"startRow":11},"structure":[],"id":146,"text":"7","parent":145,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"integerLiteral("7")"}},{"type":"other","range":{"endRow":11,"startColumn":34,"endColumn":35,"startRow":11},"structure":[],"id":147,"text":",","parent":142,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"comma"}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"kind":"identifier("count")","text":"count"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"id":148,"type":"other","text":"LabeledExpr","range":{"endRow":11,"startColumn":36,"endColumn":45,"startRow":11},"parent":141},{"type":"other","range":{"startRow":11,"endRow":11,"startColumn":36,"endColumn":41},"structure":[],"id":149,"text":"count","parent":148,"token":{"trailingTrivia":"","kind":"identifier("count")","leadingTrivia":""}},{"type":"other","range":{"startRow":11,"endRow":11,"startColumn":41,"endColumn":42},"structure":[],"id":150,"text":":","parent":148,"token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""}},{"type":"expr","id":151,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("11")","text":"11"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"range":{"startRow":11,"endRow":11,"startColumn":43,"endColumn":45},"parent":148,"text":"IntegerLiteralExpr"},{"type":"other","range":{"endRow":11,"endColumn":45,"startRow":11,"startColumn":43},"structure":[],"id":152,"text":"11","parent":151,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"integerLiteral("11")"}},{"type":"other","range":{"endRow":11,"endColumn":46,"startRow":11,"startColumn":45},"structure":[],"id":153,"text":")","parent":137,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"}},{"type":"collection","id":154,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"range":{"endRow":11,"endColumn":46,"startRow":11,"startColumn":46},"parent":137,"text":"MultipleTrailingClosureElementList"},{"type":"other","structure":[],"parent":72,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"rightSquare"},"id":155,"range":{"startRow":12,"startColumn":5,"endRow":12,"endColumn":6},"text":"]"},{"range":{"startRow":13,"endColumn":27,"startColumn":5,"endRow":13},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"value":{"text":"VariableDeclSyntax"},"name":"decl","ref":"VariableDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"id":156,"parent":60,"text":"MemberBlockItem","type":"other"},{"range":{"startColumn":5,"startRow":13,"endColumn":27,"endRow":13},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.var)","text":"var"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"id":157,"parent":156,"text":"VariableDecl","type":"decl"},{"range":{"startRow":12,"endColumn":6,"endRow":12,"startColumn":6},"structure":[{"value":{"text":"Element"},"name":"Element"},{"name":"Count","value":{"text":"0"}}],"id":158,"parent":157,"text":"AttributeList","type":"collection"},{"text":"DeclModifierList","range":{"endColumn":6,"startColumn":6,"endRow":12,"startRow":12},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","parent":157,"id":159},{"type":"other","structure":[],"parent":157,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)"},"range":{"startRow":13,"endColumn":8,"endRow":13,"startColumn":5},"id":160,"text":"var"},{"text":"PatternBindingList","range":{"startRow":13,"endColumn":27,"endRow":13,"startColumn":9},"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","parent":157,"id":161},{"text":"PatternBinding","range":{"endRow":13,"startColumn":9,"endColumn":27,"startRow":13},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other","parent":161,"id":162},{"type":"pattern","range":{"endColumn":23,"startRow":13,"startColumn":9,"endRow":13},"parent":162,"id":163,"text":"IdentifierPattern","structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"coinsDeposited","kind":"identifier("coinsDeposited")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"type":"other","structure":[],"parent":163,"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("coinsDeposited")","leadingTrivia":""},"range":{"endRow":13,"endColumn":23,"startRow":13,"startColumn":9},"id":164,"text":"coinsDeposited"},{"type":"other","range":{"endRow":13,"endColumn":27,"startRow":13,"startColumn":24},"parent":162,"id":165,"text":"InitializerClause","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}]},{"type":"other","structure":[],"parent":165,"token":{"leadingTrivia":"","kind":"equal","trailingTrivia":"␣<\/span>"},"range":{"startColumn":24,"endColumn":25,"startRow":13,"endRow":13},"id":166,"text":"="},{"type":"expr","range":{"startColumn":26,"endColumn":27,"startRow":13,"endRow":13},"parent":165,"id":167,"text":"IntegerLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"0","kind":"integerLiteral("0")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}]},{"type":"other","structure":[],"parent":167,"token":{"kind":"integerLiteral("0")","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":26,"endRow":13,"endColumn":27,"startRow":13},"id":168,"text":"0"},{"range":{"startColumn":5,"endRow":41,"endColumn":6,"startRow":16},"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","value":{"text":"FunctionDeclSyntax"},"ref":"FunctionDeclSyntax"},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":169,"type":"other","text":"MemberBlockItem","parent":60},{"range":{"endColumn":6,"startRow":16,"startColumn":5,"endRow":41},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.func)","text":"func"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("vend")","text":"vend"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"name":"signature","ref":"FunctionSignatureSyntax","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"name":"body","ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":170,"type":"decl","text":"FunctionDecl","parent":169},{"text":"AttributeList","parent":170,"range":{"endColumn":27,"endRow":13,"startColumn":27,"startRow":13},"type":"collection","id":171,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"text":"DeclModifierList","parent":170,"range":{"startColumn":27,"endRow":13,"startRow":13,"endColumn":27},"type":"collection","id":172,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"type":"other","structure":[],"parent":170,"token":{"kind":"keyword(SwiftSyntax.Keyword.func)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"endColumn":9,"startRow":16,"endRow":16,"startColumn":5},"id":173,"text":"func"},{"type":"other","structure":[],"parent":170,"token":{"kind":"identifier("vend")","trailingTrivia":"","leadingTrivia":""},"range":{"endColumn":14,"startRow":16,"endRow":16,"startColumn":10},"id":174,"text":"vend"},{"text":"FunctionSignature","parent":170,"range":{"endColumn":45,"startRow":16,"endRow":16,"startColumn":14},"type":"other","id":175,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"name":"parameterClause","ref":"FunctionParameterClauseSyntax","value":{"text":"FunctionParameterClauseSyntax"}},{"value":{"text":"nil"},"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers"},{"value":{"text":"FunctionEffectSpecifiersSyntax"},"ref":"FunctionEffectSpecifiersSyntax","name":"effectSpecifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenEffectSpecifiersAndReturnClause"},{"value":{"text":"nil"},"name":"returnClause"},{"value":{"text":"nil"},"name":"unexpectedAfterReturnClause"}]},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndParameters"},{"value":{"text":"FunctionParameterListSyntax"},"ref":"FunctionParameterListSyntax","name":"parameters"},{"value":{"text":"nil"},"name":"unexpectedBetweenParametersAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"text":"FunctionParameterClause","parent":175,"type":"other","id":176,"range":{"endRow":16,"startRow":16,"startColumn":14,"endColumn":38}},{"type":"other","structure":[],"parent":176,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"id":177,"range":{"endRow":16,"startRow":16,"startColumn":14,"endColumn":15},"text":"("},{"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"1"}}],"text":"FunctionParameterList","parent":176,"type":"collection","id":178,"range":{"endRow":16,"startRow":16,"startColumn":15,"endColumn":37}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndFirstName"},{"value":{"text":"itemNamed","kind":"identifier("itemNamed")"},"name":"firstName"},{"value":{"text":"nil"},"name":"unexpectedBetweenFirstNameAndSecondName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"secondName"},{"value":{"text":"nil"},"name":"unexpectedBetweenSecondNameAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"},"name":"type"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndEllipsis"},{"value":{"text":"nil"},"name":"ellipsis"},{"value":{"text":"nil"},"name":"unexpectedBetweenEllipsisAndDefaultValue"},{"value":{"text":"nil"},"name":"defaultValue"},{"value":{"text":"nil"},"name":"unexpectedBetweenDefaultValueAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"text":"FunctionParameter","parent":178,"type":"other","id":179,"range":{"endRow":16,"startRow":16,"endColumn":37,"startColumn":15}},{"type":"collection","id":180,"parent":179,"range":{"startRow":16,"endColumn":15,"startColumn":15,"endRow":16},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"text":"AttributeList"},{"type":"collection","id":181,"parent":179,"range":{"startColumn":15,"startRow":16,"endColumn":15,"endRow":16},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"text":"DeclModifierList"},{"type":"other","structure":[],"parent":179,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("itemNamed")"},"id":182,"range":{"startColumn":15,"endRow":16,"startRow":16,"endColumn":24},"text":"itemNamed"},{"type":"other","structure":[],"parent":179,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("name")"},"id":183,"range":{"startColumn":25,"endRow":16,"startRow":16,"endColumn":29},"text":"name"},{"type":"other","structure":[],"parent":179,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"id":184,"range":{"startColumn":29,"endRow":16,"startRow":16,"endColumn":30},"text":":"},{"type":"type","id":185,"parent":179,"range":{"startColumn":31,"endRow":16,"startRow":16,"endColumn":37},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("String")","text":"String"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"text":"IdentifierType"},{"type":"other","structure":[],"parent":185,"token":{"trailingTrivia":"","kind":"identifier("String")","leadingTrivia":""},"id":186,"range":{"endRow":16,"startRow":16,"endColumn":37,"startColumn":31},"text":"String"},{"type":"other","structure":[],"parent":176,"token":{"kind":"rightParen","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"endRow":16,"startRow":16,"startColumn":37,"endColumn":38},"id":187,"text":")"},{"parent":175,"text":"FunctionEffectSpecifiers","range":{"endRow":16,"startRow":16,"startColumn":39,"endColumn":45},"type":"other","id":188,"structure":[{"name":"unexpectedBeforeAsyncSpecifier","value":{"text":"nil"}},{"name":"asyncSpecifier","value":{"text":"nil"}},{"name":"unexpectedBetweenAsyncSpecifierAndThrowsClause","value":{"text":"nil"}},{"name":"throwsClause","ref":"ThrowsClauseSyntax","value":{"text":"ThrowsClauseSyntax"}},{"name":"unexpectedAfterThrowsClause","value":{"text":"nil"}}]},{"parent":188,"text":"ThrowsClause","range":{"endColumn":45,"startRow":16,"startColumn":39,"endRow":16},"type":"other","id":189,"structure":[{"name":"unexpectedBeforeThrowsSpecifier","value":{"text":"nil"}},{"name":"throwsSpecifier","value":{"text":"throws","kind":"keyword(SwiftSyntax.Keyword.throws)"}},{"name":"unexpectedBetweenThrowsSpecifierAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"nil"}},{"name":"unexpectedBetweenLeftParenAndType","value":{"text":"nil"}},{"name":"type","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":"nil"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"type":"other","structure":[],"parent":189,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.throws)"},"range":{"startRow":16,"startColumn":39,"endRow":16,"endColumn":45},"id":190,"text":"throws"},{"parent":170,"text":"CodeBlock","range":{"endRow":41,"endColumn":6,"startRow":16,"startColumn":46},"type":"other","structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"id":191},{"type":"other","structure":[],"parent":191,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"range":{"startColumn":46,"startRow":16,"endColumn":47,"endRow":16},"id":192,"text":"{"},{"parent":191,"text":"CodeBlockItemList","range":{"startColumn":9,"startRow":17,"endColumn":36,"endRow":40},"type":"collection","structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"8"}}],"id":193},{"parent":193,"text":"CodeBlockItem","range":{"endColumn":10,"endRow":19,"startColumn":9,"startRow":17},"type":"other","structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"GuardStmtSyntax","value":{"text":"GuardStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"id":194},{"parent":194,"text":"GuardStmt","range":{"endRow":19,"startColumn":9,"startRow":17,"endColumn":10},"type":"other","structure":[{"name":"unexpectedBeforeGuardKeyword","value":{"text":"nil"}},{"name":"guardKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.guard)","text":"guard"}},{"name":"unexpectedBetweenGuardKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax"},{"name":"unexpectedBetweenConditionsAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"id":195},{"type":"other","structure":[],"parent":195,"token":{"kind":"keyword(SwiftSyntax.Keyword.guard)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"id":196,"range":{"endRow":17,"startColumn":9,"endColumn":14,"startRow":17},"text":"guard"},{"parent":195,"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","text":"ConditionElementList","id":197,"range":{"endRow":17,"startColumn":15,"endColumn":41,"startRow":17}},{"parent":197,"structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"name":"condition","value":{"text":"OptionalBindingConditionSyntax"},"ref":"OptionalBindingConditionSyntax"},{"name":"unexpectedBetweenConditionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","text":"ConditionElement","id":198,"range":{"endRow":17,"startColumn":15,"startRow":17,"endColumn":41}},{"type":"other","structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedAfterInitializer","value":{"text":"nil"}}],"range":{"endRow":17,"startColumn":15,"endColumn":41,"startRow":17},"id":199,"parent":198,"text":"OptionalBindingCondition"},{"type":"other","structure":[],"parent":199,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)"},"range":{"endRow":17,"startColumn":15,"startRow":17,"endColumn":18},"id":200,"text":"let"},{"type":"pattern","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"kind":"identifier("item")","text":"item"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}],"range":{"endRow":17,"startColumn":19,"startRow":17,"endColumn":23},"id":201,"parent":199,"text":"IdentifierPattern"},{"type":"other","structure":[],"parent":201,"token":{"kind":"identifier("item")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":17,"endRow":17,"endColumn":23,"startColumn":19},"id":202,"text":"item"},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"kind":"equal","text":"="},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"SubscriptCallExprSyntax"},"ref":"SubscriptCallExprSyntax","name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}],"type":"other","parent":199,"id":203,"text":"InitializerClause","range":{"startColumn":24,"startRow":17,"endColumn":41,"endRow":17}},{"type":"other","structure":[],"parent":203,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"equal"},"id":204,"range":{"endRow":17,"endColumn":25,"startColumn":24,"startRow":17},"text":"="},{"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"text":"[","kind":"leftSquare"}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","parent":203,"id":205,"text":"SubscriptCallExpr","range":{"endRow":17,"endColumn":41,"startColumn":26,"startRow":17}},{"range":{"endColumn":35,"endRow":17,"startColumn":26,"startRow":17},"id":206,"parent":205,"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"inventory","kind":"identifier("inventory")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"type":"other","structure":[],"parent":206,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("inventory")"},"range":{"endColumn":35,"endRow":17,"startRow":17,"startColumn":26},"id":207,"text":"inventory"},{"type":"other","structure":[],"parent":205,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftSquare"},"range":{"endColumn":36,"endRow":17,"startRow":17,"startColumn":35},"id":208,"text":"["},{"range":{"endColumn":40,"endRow":17,"startRow":17,"startColumn":36},"id":209,"parent":205,"text":"LabeledExprList","structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection"},{"range":{"endRow":17,"startRow":17,"startColumn":36,"endColumn":40},"id":210,"parent":209,"text":"LabeledExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"type":"other"},{"text":"DeclReferenceExpr","id":211,"range":{"startColumn":36,"startRow":17,"endColumn":40,"endRow":17},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"name","kind":"identifier("name")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","parent":210},{"text":"name","parent":211,"range":{"startRow":17,"startColumn":36,"endRow":17,"endColumn":40},"token":{"trailingTrivia":"","kind":"identifier("name")","leadingTrivia":""},"id":212,"type":"other","structure":[]},{"text":"]","parent":205,"range":{"startRow":17,"startColumn":40,"endRow":17,"endColumn":41},"token":{"trailingTrivia":"␣<\/span>","kind":"rightSquare","leadingTrivia":""},"id":213,"type":"other","structure":[]},{"text":"MultipleTrailingClosureElementList","id":214,"range":{"startRow":17,"startColumn":42,"endRow":17,"endColumn":42},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","parent":205},{"text":"else","parent":195,"range":{"startRow":17,"startColumn":42,"endColumn":46,"endRow":17},"token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.else)","trailingTrivia":"␣<\/span>"},"id":215,"type":"other","structure":[]},{"range":{"endRow":19,"endColumn":10,"startRow":17,"startColumn":47},"type":"other","structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"text":"CodeBlock","id":216,"parent":195},{"text":"{","parent":216,"range":{"startColumn":47,"startRow":17,"endColumn":48,"endRow":17},"token":{"kind":"leftBrace","trailingTrivia":"","leadingTrivia":""},"id":217,"type":"other","structure":[]},{"range":{"startColumn":13,"startRow":18,"endColumn":55,"endRow":18},"type":"collection","structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"CodeBlockItemList","id":218,"parent":216},{"range":{"startColumn":13,"endRow":18,"endColumn":55,"startRow":18},"type":"other","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ThrowStmtSyntax","value":{"text":"ThrowStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"text":"CodeBlockItem","id":219,"parent":218},{"range":{"endRow":18,"endColumn":55,"startRow":18,"startColumn":13},"type":"other","structure":[{"name":"unexpectedBeforeThrowKeyword","value":{"text":"nil"}},{"name":"throwKeyword","value":{"text":"throw","kind":"keyword(SwiftSyntax.Keyword.throw)"}},{"name":"unexpectedBetweenThrowKeywordAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}],"text":"ThrowStmt","id":220,"parent":219},{"text":"throw","parent":220,"range":{"startColumn":13,"startRow":18,"endColumn":18,"endRow":18},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.throw)"},"id":221,"type":"other","structure":[]},{"id":222,"parent":220,"type":"expr","text":"MemberAccessExpr","range":{"startColumn":19,"startRow":18,"endColumn":55,"endRow":18},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"base","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"declName","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}]},{"id":223,"parent":222,"type":"expr","text":"DeclReferenceExpr","range":{"endRow":18,"startColumn":19,"endColumn":38,"startRow":18},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("VendingMachineError")","text":"VendingMachineError"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"text":"VendingMachineError","parent":223,"range":{"startRow":18,"endRow":18,"endColumn":38,"startColumn":19},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("VendingMachineError")"},"id":224,"type":"other","structure":[]},{"text":".","parent":222,"range":{"startRow":18,"endRow":18,"endColumn":39,"startColumn":38},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"period"},"id":225,"type":"other","structure":[]},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"invalidSelection","kind":"identifier("invalidSelection")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","range":{"startRow":18,"endRow":18,"endColumn":55,"startColumn":39},"type":"expr","parent":222,"id":226},{"text":"invalidSelection","parent":226,"range":{"endRow":18,"startColumn":39,"endColumn":55,"startRow":18},"token":{"leadingTrivia":"","kind":"identifier("invalidSelection")","trailingTrivia":""},"id":227,"type":"other","structure":[]},{"text":"}","parent":216,"range":{"endRow":19,"startColumn":9,"endColumn":10,"startRow":19},"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"rightBrace","trailingTrivia":""},"id":228,"type":"other","structure":[]},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"GuardStmtSyntax"},"ref":"GuardStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","range":{"endRow":24,"startColumn":9,"endColumn":10,"startRow":22},"type":"other","parent":193,"id":229},{"text":"GuardStmt","structure":[{"name":"unexpectedBeforeGuardKeyword","value":{"text":"nil"}},{"name":"guardKeyword","value":{"text":"guard","kind":"keyword(SwiftSyntax.Keyword.guard)"}},{"name":"unexpectedBetweenGuardKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax"},{"name":"unexpectedBetweenConditionsAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"type":"other","parent":229,"id":230,"range":{"startRow":22,"endColumn":10,"startColumn":9,"endRow":24}},{"text":"guard","parent":230,"range":{"startColumn":9,"endRow":22,"startRow":22,"endColumn":14},"token":{"kind":"keyword(SwiftSyntax.Keyword.guard)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"id":231,"type":"other","structure":[]},{"text":"ConditionElementList","structure":[{"value":{"text":"ConditionElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"type":"collection","parent":230,"id":232,"range":{"startColumn":15,"endRow":22,"startRow":22,"endColumn":29}},{"text":"ConditionElement","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"},"name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":232,"id":233,"range":{"endColumn":29,"startColumn":15,"startRow":22,"endRow":22}},{"text":"InfixOperatorExpr","parent":233,"range":{"endColumn":29,"endRow":22,"startRow":22,"startColumn":15},"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","id":234},{"text":"MemberAccessExpr","parent":234,"range":{"startColumn":15,"endRow":22,"endColumn":25,"startRow":22},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"type":"expr","id":235},{"parent":235,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("item")","text":"item"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","type":"expr","id":236,"range":{"endRow":22,"startColumn":15,"endColumn":19,"startRow":22}},{"text":"item","parent":236,"range":{"startColumn":15,"endRow":22,"startRow":22,"endColumn":19},"token":{"leadingTrivia":"","kind":"identifier("item")","trailingTrivia":""},"id":237,"type":"other","structure":[]},{"text":".","parent":235,"range":{"startColumn":19,"endRow":22,"startRow":22,"endColumn":20},"token":{"leadingTrivia":"","kind":"period","trailingTrivia":""},"id":238,"type":"other","structure":[]},{"parent":235,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("count")","text":"count"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","type":"expr","id":239,"range":{"startColumn":20,"endRow":22,"startRow":22,"endColumn":25}},{"text":"count","parent":239,"range":{"startColumn":20,"startRow":22,"endRow":22,"endColumn":25},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("count")"},"id":240,"type":"other","structure":[]},{"parent":234,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"kind":"binaryOperator(">")","text":">"}},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"text":"BinaryOperatorExpr","type":"expr","id":241,"range":{"startColumn":26,"startRow":22,"endRow":22,"endColumn":27}},{"text":">","parent":241,"range":{"startColumn":26,"startRow":22,"endColumn":27,"endRow":22},"token":{"trailingTrivia":"␣<\/span>","kind":"binaryOperator(">")","leadingTrivia":""},"id":242,"type":"other","structure":[]},{"text":"IntegerLiteralExpr","id":243,"parent":234,"range":{"startColumn":28,"startRow":22,"endColumn":29,"endRow":22},"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"0","kind":"integerLiteral("0")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr"},{"text":"0","parent":243,"range":{"endRow":22,"startRow":22,"endColumn":29,"startColumn":28},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"integerLiteral("0")"},"id":244,"type":"other","structure":[]},{"text":"else","parent":230,"range":{"endRow":22,"startRow":22,"endColumn":34,"startColumn":30},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.else)"},"id":245,"type":"other","structure":[]},{"text":"CodeBlock","id":246,"parent":230,"range":{"endRow":24,"startRow":22,"endColumn":10,"startColumn":35},"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"ref":"CodeBlockItemListSyntax","name":"statements","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"type":"other"},{"text":"{","parent":246,"range":{"startColumn":35,"endRow":22,"endColumn":36,"startRow":22},"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"id":247,"type":"other","structure":[]},{"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":248,"parent":246,"text":"CodeBlockItemList","range":{"endColumn":49,"startColumn":13,"endRow":23,"startRow":23}},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"ThrowStmtSyntax","value":{"text":"ThrowStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","id":249,"parent":248,"text":"CodeBlockItem","range":{"endRow":23,"endColumn":49,"startColumn":13,"startRow":23}},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeThrowKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.throw)","text":"throw"},"name":"throwKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenThrowKeywordAndExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"other","id":250,"parent":249,"text":"ThrowStmt","range":{"endColumn":49,"startColumn":13,"startRow":23,"endRow":23}},{"text":"throw","parent":250,"range":{"startRow":23,"endColumn":18,"startColumn":13,"endRow":23},"token":{"kind":"keyword(SwiftSyntax.Keyword.throw)","trailingTrivia":"␣<\/span>","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"id":251,"type":"other","structure":[]},{"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"type":"expr","id":252,"parent":250,"text":"MemberAccessExpr","range":{"startRow":23,"endColumn":49,"startColumn":19,"endRow":23}},{"range":{"startColumn":19,"endRow":23,"endColumn":38,"startRow":23},"parent":252,"text":"DeclReferenceExpr","id":253,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("VendingMachineError")","text":"VendingMachineError"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"text":"VendingMachineError","parent":253,"range":{"startColumn":19,"startRow":23,"endRow":23,"endColumn":38},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("VendingMachineError")"},"id":254,"type":"other","structure":[]},{"text":".","parent":252,"range":{"startColumn":38,"startRow":23,"endRow":23,"endColumn":39},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"},"id":255,"type":"other","structure":[]},{"range":{"startColumn":39,"startRow":23,"endRow":23,"endColumn":49},"parent":252,"text":"DeclReferenceExpr","id":256,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"outOfStock","kind":"identifier("outOfStock")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"text":"outOfStock","parent":256,"range":{"endColumn":49,"startColumn":39,"endRow":23,"startRow":23},"token":{"trailingTrivia":"","kind":"identifier("outOfStock")","leadingTrivia":""},"id":257,"type":"other","structure":[]},{"parent":246,"id":258,"type":"other","token":{"trailingTrivia":"","kind":"rightBrace","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"range":{"endColumn":10,"startColumn":9,"endRow":24,"startRow":24},"text":"}"},{"range":{"endColumn":10,"startColumn":9,"endRow":29,"startRow":27},"id":259,"text":"CodeBlockItem","parent":193,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"GuardStmtSyntax"},"ref":"GuardStmtSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other"},{"range":{"endRow":29,"endColumn":10,"startColumn":9,"startRow":27},"id":260,"text":"GuardStmt","parent":259,"structure":[{"name":"unexpectedBeforeGuardKeyword","value":{"text":"nil"}},{"name":"guardKeyword","value":{"text":"guard","kind":"keyword(SwiftSyntax.Keyword.guard)"}},{"name":"unexpectedBetweenGuardKeywordAndConditions","value":{"text":"nil"}},{"name":"conditions","value":{"text":"ConditionElementListSyntax"},"ref":"ConditionElementListSyntax"},{"name":"unexpectedBetweenConditionsAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}],"type":"other"},{"parent":260,"id":261,"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.guard)","leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"structure":[],"range":{"startColumn":9,"startRow":27,"endRow":27,"endColumn":14},"text":"guard"},{"parent":260,"type":"collection","id":262,"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}],"range":{"startColumn":15,"startRow":27,"endRow":27,"endColumn":43},"text":"ConditionElementList"},{"parent":262,"type":"other","id":263,"structure":[{"name":"unexpectedBeforeCondition","value":{"text":"nil"}},{"name":"condition","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenConditionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"range":{"endRow":27,"startRow":27,"startColumn":15,"endColumn":43},"text":"ConditionElement"},{"parent":263,"type":"expr","id":264,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"range":{"startColumn":15,"startRow":27,"endColumn":43,"endRow":27},"text":"InfixOperatorExpr"},{"parent":264,"text":"MemberAccessExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"base","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"declName","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"type":"expr","range":{"startRow":27,"endColumn":25,"endRow":27,"startColumn":15},"id":265},{"parent":265,"text":"DeclReferenceExpr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"item","kind":"identifier("item")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","range":{"startColumn":15,"endRow":27,"endColumn":19,"startRow":27},"id":266},{"parent":266,"id":267,"type":"other","token":{"kind":"identifier("item")","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"startColumn":15,"startRow":27,"endColumn":19,"endRow":27},"text":"item"},{"parent":265,"id":268,"type":"other","token":{"kind":"period","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"startRow":27,"endRow":27,"startColumn":19,"endColumn":20},"text":"."},{"parent":265,"text":"DeclReferenceExpr","id":269,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("price")","text":"price"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","range":{"endColumn":25,"startRow":27,"endRow":27,"startColumn":20}},{"parent":269,"id":270,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("price")"},"structure":[],"range":{"startColumn":20,"endColumn":25,"startRow":27,"endRow":27},"text":"price"},{"parent":264,"text":"BinaryOperatorExpr","id":271,"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"<=","kind":"binaryOperator("<=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","range":{"startColumn":26,"endColumn":28,"startRow":27,"endRow":27}},{"parent":271,"id":272,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"binaryOperator("<=")"},"structure":[],"range":{"startRow":27,"endRow":27,"startColumn":26,"endColumn":28},"text":"<="},{"parent":264,"text":"DeclReferenceExpr","id":273,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("coinsDeposited")","text":"coinsDeposited"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr","range":{"startRow":27,"endRow":27,"startColumn":29,"endColumn":43}},{"parent":273,"id":274,"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("coinsDeposited")","leadingTrivia":""},"structure":[],"range":{"startRow":27,"startColumn":29,"endRow":27,"endColumn":43},"text":"coinsDeposited"},{"parent":260,"id":275,"type":"other","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.else)"},"structure":[],"range":{"startColumn":44,"startRow":27,"endRow":27,"endColumn":48},"text":"else"},{"text":"CodeBlock","range":{"startColumn":49,"startRow":27,"endRow":29,"endColumn":10},"parent":260,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"type":"other","id":276},{"parent":276,"id":277,"type":"other","token":{"kind":"leftBrace","trailingTrivia":"","leadingTrivia":""},"structure":[],"range":{"startColumn":49,"endColumn":50,"startRow":27,"endRow":27},"text":"{"},{"text":"CodeBlockItemList","range":{"startColumn":13,"endColumn":98,"startRow":28,"endRow":28},"parent":276,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","id":278},{"text":"CodeBlockItem","range":{"startColumn":13,"endColumn":98,"endRow":28,"startRow":28},"parent":278,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"ThrowStmtSyntax","value":{"text":"ThrowStmtSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","id":279},{"range":{"startRow":28,"endRow":28,"endColumn":98,"startColumn":13},"parent":279,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeThrowKeyword"},{"value":{"text":"throw","kind":"keyword(SwiftSyntax.Keyword.throw)"},"name":"throwKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenThrowKeywordAndExpression"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}],"type":"other","text":"ThrowStmt","id":280},{"parent":280,"id":281,"type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.throw)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>"},"structure":[],"range":{"startRow":28,"endRow":28,"endColumn":18,"startColumn":13},"text":"throw"},{"range":{"startRow":28,"endRow":28,"endColumn":98,"startColumn":19},"parent":280,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"type":"expr","text":"FunctionCallExpr","id":282},{"text":"MemberAccessExpr","id":283,"parent":282,"range":{"startColumn":19,"endRow":28,"startRow":28,"endColumn":56},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"base","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"declName","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}]},{"text":"DeclReferenceExpr","id":284,"parent":283,"range":{"endRow":28,"endColumn":38,"startColumn":19,"startRow":28},"type":"expr","structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"VendingMachineError","kind":"identifier("VendingMachineError")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"parent":284,"id":285,"type":"other","token":{"trailingTrivia":"","kind":"identifier("VendingMachineError")","leadingTrivia":""},"structure":[],"range":{"endColumn":38,"startRow":28,"startColumn":19,"endRow":28},"text":"VendingMachineError"},{"parent":283,"id":286,"type":"other","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"structure":[],"range":{"endColumn":39,"startRow":28,"startColumn":38,"endRow":28},"text":"."},{"text":"DeclReferenceExpr","id":287,"parent":283,"range":{"endColumn":56,"startRow":28,"startColumn":39,"endRow":28},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"insufficientFunds","kind":"identifier("insufficientFunds")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"parent":287,"id":288,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("insufficientFunds")"},"structure":[],"range":{"startRow":28,"endRow":28,"startColumn":39,"endColumn":56},"text":"insufficientFunds"},{"parent":282,"id":289,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"structure":[],"range":{"startRow":28,"endRow":28,"startColumn":56,"endColumn":57},"text":"("},{"text":"LabeledExprList","id":290,"parent":282,"range":{"startRow":28,"endRow":28,"startColumn":57,"endColumn":97},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection"},{"text":"LabeledExpr","id":291,"parent":290,"range":{"startRow":28,"startColumn":57,"endRow":28,"endColumn":97},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"kind":"identifier("coinsNeeded")","text":"coinsNeeded"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other"},{"parent":291,"id":292,"type":"other","token":{"trailingTrivia":"","kind":"identifier("coinsNeeded")","leadingTrivia":""},"structure":[],"range":{"startRow":28,"endRow":28,"startColumn":57,"endColumn":68},"text":"coinsNeeded"},{"parent":291,"id":293,"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""},"structure":[],"range":{"startRow":28,"endRow":28,"startColumn":68,"endColumn":69},"text":":"},{"id":294,"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","range":{"startRow":28,"endRow":28,"startColumn":70,"endColumn":97},"parent":291,"text":"InfixOperatorExpr"},{"id":295,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"base","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"type":"expr","range":{"startRow":28,"endColumn":80,"endRow":28,"startColumn":70},"parent":294,"text":"MemberAccessExpr"},{"parent":295,"id":296,"text":"DeclReferenceExpr","range":{"startColumn":70,"startRow":28,"endRow":28,"endColumn":74},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"item","kind":"identifier("item")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr"},{"parent":296,"id":297,"type":"other","token":{"leadingTrivia":"","kind":"identifier("item")","trailingTrivia":""},"structure":[],"range":{"startColumn":70,"startRow":28,"endColumn":74,"endRow":28},"text":"item"},{"parent":295,"id":298,"type":"other","token":{"leadingTrivia":"","kind":"period","trailingTrivia":""},"structure":[],"range":{"startColumn":74,"startRow":28,"endColumn":75,"endRow":28},"text":"."},{"parent":295,"id":299,"text":"DeclReferenceExpr","range":{"startColumn":75,"startRow":28,"endColumn":80,"endRow":28},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"price","kind":"identifier("price")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"parent":299,"id":300,"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("price")"},"structure":[],"range":{"startRow":28,"startColumn":75,"endRow":28,"endColumn":80},"text":"price"},{"type":"expr","id":301,"text":"BinaryOperatorExpr","range":{"startRow":28,"startColumn":81,"endRow":28,"endColumn":82},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"binaryOperator("-")","text":"-"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedAfterOperator"}],"parent":294},{"parent":301,"id":302,"type":"other","token":{"leadingTrivia":"","kind":"binaryOperator("-")","trailingTrivia":"␣<\/span>"},"structure":[],"range":{"endColumn":82,"startRow":28,"startColumn":81,"endRow":28},"text":"-"},{"type":"expr","id":303,"text":"DeclReferenceExpr","range":{"endColumn":97,"startRow":28,"startColumn":83,"endRow":28},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("coinsDeposited")","text":"coinsDeposited"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":294},{"parent":303,"id":304,"type":"other","token":{"kind":"identifier("coinsDeposited")","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"endRow":28,"startColumn":83,"endColumn":97,"startRow":28},"text":"coinsDeposited"},{"parent":282,"type":"other","range":{"endRow":28,"startColumn":97,"endColumn":98,"startRow":28},"structure":[],"text":")","id":305,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""}},{"type":"collection","id":306,"text":"MultipleTrailingClosureElementList","range":{"endRow":28,"startColumn":98,"endColumn":98,"startRow":28},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":282},{"parent":276,"type":"other","range":{"endColumn":10,"endRow":29,"startRow":29,"startColumn":9},"structure":[],"text":"}","id":307,"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""}},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","parent":193,"text":"CodeBlockItem","range":{"endColumn":37,"endRow":32,"startRow":32,"startColumn":9},"id":308},{"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","ref":"BinaryOperatorExprSyntax","value":{"text":"BinaryOperatorExprSyntax"}},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"}},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","parent":308,"text":"InfixOperatorExpr","range":{"startRow":32,"endRow":32,"startColumn":9,"endColumn":37},"id":309},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("coinsDeposited")","text":"coinsDeposited"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","parent":309,"text":"DeclReferenceExpr","range":{"startRow":32,"startColumn":9,"endRow":32,"endColumn":23},"id":310},{"parent":310,"type":"other","range":{"endRow":32,"endColumn":23,"startRow":32,"startColumn":9},"structure":[],"text":"coinsDeposited","id":311,"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("coinsDeposited")","leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"}},{"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"-=","kind":"binaryOperator("-=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","id":312,"range":{"endRow":32,"endColumn":26,"startRow":32,"startColumn":24},"parent":309,"text":"BinaryOperatorExpr"},{"parent":312,"type":"other","range":{"endColumn":26,"endRow":32,"startRow":32,"startColumn":24},"structure":[],"text":"-=","id":313,"token":{"kind":"binaryOperator("-=")","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"base","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"type":"expr","id":314,"range":{"endColumn":37,"endRow":32,"startRow":32,"startColumn":27},"parent":309,"text":"MemberAccessExpr"},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"item","kind":"identifier("item")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","id":315,"range":{"startColumn":27,"endRow":32,"startRow":32,"endColumn":31},"parent":314,"text":"DeclReferenceExpr"},{"parent":315,"type":"other","range":{"endColumn":31,"endRow":32,"startColumn":27,"startRow":32},"structure":[],"text":"item","id":316,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("item")"}},{"parent":314,"type":"other","range":{"endColumn":32,"endRow":32,"startColumn":31,"startRow":32},"structure":[],"text":".","id":317,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"}},{"range":{"endColumn":37,"endRow":32,"startColumn":32,"startRow":32},"id":318,"parent":314,"text":"DeclReferenceExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"price","kind":"identifier("price")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"type":"expr"},{"parent":318,"type":"other","range":{"endRow":32,"startRow":32,"startColumn":32,"endColumn":37},"structure":[],"text":"price","id":319,"token":{"leadingTrivia":"","kind":"identifier("price")","trailingTrivia":""}},{"range":{"endRow":35,"startRow":35,"startColumn":9,"endColumn":27},"id":320,"parent":193,"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other"},{"text":"VariableDecl","id":321,"range":{"startRow":35,"startColumn":9,"endColumn":27,"endRow":35},"type":"decl","structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"parent":320},{"text":"AttributeList","id":322,"range":{"endRow":32,"startRow":32,"endColumn":37,"startColumn":37},"type":"collection","structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":321},{"text":"DeclModifierList","id":323,"range":{"startRow":32,"startColumn":37,"endRow":32,"endColumn":37},"type":"collection","structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":321},{"parent":321,"type":"other","range":{"startColumn":9,"endColumn":12,"endRow":35,"startRow":35},"structure":[],"text":"var","id":324,"token":{"leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)"}},{"parent":321,"range":{"startColumn":13,"endColumn":27,"endRow":35,"startRow":35},"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"text":"PatternBindingList","type":"collection","id":325},{"parent":325,"range":{"startRow":35,"startColumn":13,"endRow":35,"endColumn":27},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"ref":"InitializerClauseSyntax","value":{"text":"InitializerClauseSyntax"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"text":"PatternBinding","type":"other","id":326},{"parent":326,"range":{"startRow":35,"endRow":35,"startColumn":13,"endColumn":20},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"name":"identifier","value":{"kind":"identifier("newItem")","text":"newItem"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"text":"IdentifierPattern","type":"pattern","id":327},{"parent":327,"type":"other","range":{"startColumn":13,"endRow":35,"endColumn":20,"startRow":35},"structure":[],"text":"newItem","id":328,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"identifier("newItem")"}},{"type":"other","text":"InitializerClause","parent":326,"range":{"startColumn":21,"endRow":35,"endColumn":27,"startRow":35},"id":329,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"value","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"parent":329,"type":"other","range":{"startRow":35,"endRow":35,"endColumn":22,"startColumn":21},"structure":[],"text":"=","id":330,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"equal"}},{"type":"expr","text":"DeclReferenceExpr","parent":329,"range":{"startRow":35,"endRow":35,"endColumn":27,"startColumn":23},"id":331,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"item","kind":"identifier("item")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"parent":331,"type":"other","range":{"endColumn":27,"endRow":35,"startColumn":23,"startRow":35},"structure":[],"text":"item","id":332,"token":{"kind":"identifier("item")","leadingTrivia":"","trailingTrivia":""}},{"parent":193,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"InfixOperatorExprSyntax"},"name":"item","ref":"InfixOperatorExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"type":"other","text":"CodeBlockItem","range":{"startColumn":9,"startRow":36,"endColumn":27,"endRow":36},"id":333},{"parent":333,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"value":{"text":"BinaryOperatorExprSyntax"},"ref":"BinaryOperatorExprSyntax","name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax","name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}],"type":"expr","text":"InfixOperatorExpr","range":{"startRow":36,"endRow":36,"endColumn":27,"startColumn":9},"id":334},{"parent":334,"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"type":"expr","text":"MemberAccessExpr","range":{"startRow":36,"endColumn":22,"endRow":36,"startColumn":9},"id":335},{"type":"expr","parent":335,"id":336,"text":"DeclReferenceExpr","range":{"endRow":36,"startRow":36,"startColumn":9,"endColumn":16},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"newItem","kind":"identifier("newItem")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"parent":336,"type":"other","range":{"startColumn":9,"endRow":36,"startRow":36,"endColumn":16},"structure":[],"text":"newItem","id":337,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("newItem")"}},{"parent":335,"type":"other","range":{"startColumn":16,"endRow":36,"startRow":36,"endColumn":17},"structure":[],"text":".","id":338,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"period"}},{"type":"expr","parent":335,"id":339,"text":"DeclReferenceExpr","range":{"startColumn":17,"endRow":36,"startRow":36,"endColumn":22},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"count","kind":"identifier("count")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"parent":339,"type":"other","range":{"endColumn":22,"startColumn":17,"startRow":36,"endRow":36},"structure":[],"text":"count","id":340,"token":{"kind":"identifier("count")","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"structure":[{"name":"unexpectedBeforeOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"-=","kind":"binaryOperator("-=")"}},{"name":"unexpectedAfterOperator","value":{"text":"nil"}}],"type":"expr","id":341,"parent":334,"text":"BinaryOperatorExpr","range":{"startRow":36,"endRow":36,"startColumn":23,"endColumn":25}},{"parent":341,"type":"other","range":{"endRow":36,"startRow":36,"startColumn":23,"endColumn":25},"structure":[],"text":"-=","id":342,"token":{"kind":"binaryOperator("-=")","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"kind":"integerLiteral("1")","text":"1"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}],"type":"expr","id":343,"parent":334,"text":"IntegerLiteralExpr","range":{"endRow":36,"startRow":36,"startColumn":26,"endColumn":27}},{"parent":343,"type":"other","range":{"startColumn":26,"startRow":36,"endColumn":27,"endRow":36},"structure":[],"text":"1","id":344,"token":{"trailingTrivia":"","kind":"integerLiteral("1")","leadingTrivia":""}},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"InfixOperatorExprSyntax"},"ref":"InfixOperatorExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"type":"other","id":345,"parent":193,"text":"CodeBlockItem","range":{"startColumn":9,"startRow":37,"endColumn":34,"endRow":37}},{"structure":[{"name":"unexpectedBeforeLeftOperand","value":{"text":"nil"}},{"name":"leftOperand","value":{"text":"SubscriptCallExprSyntax"},"ref":"SubscriptCallExprSyntax"},{"name":"unexpectedBetweenLeftOperandAndOperator","value":{"text":"nil"}},{"name":"operator","value":{"text":"AssignmentExprSyntax"},"ref":"AssignmentExprSyntax"},{"name":"unexpectedBetweenOperatorAndRightOperand","value":{"text":"nil"}},{"name":"rightOperand","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterRightOperand","value":{"text":"nil"}}],"type":"expr","id":346,"parent":345,"text":"InfixOperatorExpr","range":{"startRow":37,"startColumn":9,"endRow":37,"endColumn":34}},{"id":347,"text":"SubscriptCallExpr","type":"expr","range":{"startColumn":9,"endRow":37,"endColumn":24,"startRow":37},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftSquare","value":{"text":"nil"}},{"name":"leftSquare","value":{"kind":"leftSquare","text":"["}},{"name":"unexpectedBetweenLeftSquareAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightSquare","value":{"text":"nil"}},{"name":"rightSquare","value":{"kind":"rightSquare","text":"]"}},{"name":"unexpectedBetweenRightSquareAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"parent":346},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"inventory","kind":"identifier("inventory")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"type":"expr","parent":347,"id":348,"text":"DeclReferenceExpr","range":{"startColumn":9,"endRow":37,"endColumn":18,"startRow":37}},{"parent":348,"type":"other","range":{"endRow":37,"startRow":37,"startColumn":9,"endColumn":18},"structure":[],"text":"inventory","id":349,"token":{"kind":"identifier("inventory")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""}},{"parent":347,"type":"other","range":{"endRow":37,"startRow":37,"startColumn":18,"endColumn":19},"structure":[],"text":"[","id":350,"token":{"kind":"leftSquare","leadingTrivia":"","trailingTrivia":""}},{"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"type":"collection","parent":347,"id":351,"text":"LabeledExprList","range":{"endRow":37,"startRow":37,"startColumn":19,"endColumn":23}},{"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"expression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"type":"other","parent":351,"id":352,"text":"LabeledExpr","range":{"startRow":37,"endRow":37,"startColumn":19,"endColumn":23}},{"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("name")","text":"name"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"id":353,"type":"expr","parent":352,"range":{"startColumn":19,"startRow":37,"endRow":37,"endColumn":23},"text":"DeclReferenceExpr"},{"parent":353,"type":"other","range":{"startRow":37,"endRow":37,"startColumn":19,"endColumn":23},"structure":[],"text":"name","id":354,"token":{"trailingTrivia":"","kind":"identifier("name")","leadingTrivia":""}},{"parent":347,"type":"other","range":{"startRow":37,"endRow":37,"startColumn":23,"endColumn":24},"structure":[],"text":"]","id":355,"token":{"trailingTrivia":"␣<\/span>","kind":"rightSquare","leadingTrivia":""}},{"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"id":356,"type":"collection","parent":347,"range":{"startRow":37,"endRow":37,"startColumn":25,"endColumn":25},"text":"MultipleTrailingClosureElementList"},{"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedAfterEqual"}],"id":357,"type":"expr","parent":346,"range":{"endColumn":26,"startRow":37,"startColumn":25,"endRow":37},"text":"AssignmentExpr"},{"parent":357,"type":"other","range":{"startColumn":25,"endRow":37,"endColumn":26,"startRow":37},"structure":[],"text":"=","id":358,"token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"id":359,"text":"DeclReferenceExpr","range":{"startColumn":27,"endRow":37,"endColumn":34,"startRow":37},"type":"expr","parent":346,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"newItem","kind":"identifier("newItem")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"text":"newItem","range":{"endRow":37,"endColumn":34,"startRow":37,"startColumn":27},"parent":359,"token":{"kind":"identifier("newItem")","leadingTrivia":"","trailingTrivia":""},"type":"other","structure":[],"id":360},{"id":361,"text":"CodeBlockItem","range":{"endRow":40,"endColumn":36,"startRow":40,"startColumn":9},"type":"other","parent":193,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"id":362,"text":"FunctionCallExpr","range":{"endRow":40,"startColumn":9,"startRow":40,"endColumn":36},"type":"expr","parent":361,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"id":363,"text":"DeclReferenceExpr","parent":362,"range":{"endColumn":14,"endRow":40,"startColumn":9,"startRow":40},"type":"expr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"print","parent":363,"range":{"startColumn":9,"startRow":40,"endRow":40,"endColumn":14},"token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"type":"other","structure":[],"id":364},{"text":"(","parent":362,"range":{"startColumn":14,"startRow":40,"endRow":40,"endColumn":15},"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"type":"other","structure":[],"id":365},{"text":"LabeledExprList","structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"id":366,"parent":362,"range":{"startColumn":15,"startRow":40,"endRow":40,"endColumn":35},"type":"collection"},{"text":"LabeledExpr","structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"id":367,"parent":366,"range":{"startColumn":15,"endColumn":35,"endRow":40,"startRow":40},"type":"other"},{"text":"StringLiteralExpr","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"id":368,"parent":367,"range":{"endColumn":35,"startRow":40,"startColumn":15,"endRow":40},"type":"expr"},{"parent":368,"text":""","range":{"startRow":40,"endColumn":16,"startColumn":15,"endRow":40},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"type":"other","structure":[],"id":369},{"id":370,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}],"type":"collection","parent":368,"text":"StringLiteralSegmentList","range":{"startRow":40,"endColumn":34,"startColumn":16,"endRow":40}},{"id":371,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Dispensing ")","text":"Dispensing "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"type":"other","parent":370,"text":"StringSegment","range":{"startColumn":16,"endRow":40,"endColumn":27,"startRow":40}},{"parent":371,"text":"Dispensing␣<\/span>","range":{"endColumn":27,"startRow":40,"startColumn":16,"endRow":40},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("Dispensing ")"},"type":"other","structure":[],"id":372},{"text":"ExpressionSegment","id":373,"range":{"startRow":40,"startColumn":27,"endRow":40,"endColumn":34},"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":370,"type":"other"},{"text":"\\","range":{"startRow":40,"startColumn":27,"endColumn":28,"endRow":40},"parent":373,"token":{"kind":"backslash","leadingTrivia":"","trailingTrivia":""},"type":"other","structure":[],"id":374},{"text":"(","range":{"startRow":40,"startColumn":28,"endColumn":29,"endRow":40},"parent":373,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"type":"other","structure":[],"id":375},{"text":"LabeledExprList","id":376,"range":{"startRow":40,"startColumn":29,"endColumn":33,"endRow":40},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":373,"type":"collection"},{"text":"LabeledExpr","id":377,"range":{"startRow":40,"endColumn":33,"startColumn":29,"endRow":40},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":376,"type":"other"},{"type":"expr","id":378,"parent":377,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("name")","text":"name"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"text":"DeclReferenceExpr","range":{"startColumn":29,"endRow":40,"startRow":40,"endColumn":33}},{"parent":378,"text":"name","range":{"startRow":40,"endRow":40,"endColumn":33,"startColumn":29},"token":{"kind":"identifier("name")","leadingTrivia":"","trailingTrivia":""},"type":"other","structure":[],"id":379},{"parent":373,"text":")","range":{"startRow":40,"endRow":40,"endColumn":34,"startColumn":33},"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"type":"other","structure":[],"id":380},{"parent":370,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"","kind":"stringSegment("")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"type":"other","id":381,"range":{"endRow":40,"endColumn":34,"startRow":40,"startColumn":34},"text":"StringSegment"},{"parent":381,"range":{"startRow":40,"endRow":40,"endColumn":34,"startColumn":34},"text":"","token":{"leadingTrivia":"","kind":"stringSegment("")","trailingTrivia":""},"type":"other","structure":[],"id":382},{"parent":368,"range":{"startRow":40,"endRow":40,"endColumn":35,"startColumn":34},"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"type":"other","structure":[],"id":383},{"parent":362,"range":{"startRow":40,"endRow":40,"endColumn":36,"startColumn":35},"text":")","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"type":"other","structure":[],"id":384},{"parent":362,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"type":"collection","id":385,"range":{"startRow":40,"endRow":40,"endColumn":36,"startColumn":36},"text":"MultipleTrailingClosureElementList"},{"parent":191,"range":{"startRow":41,"endColumn":6,"startColumn":5,"endRow":41},"text":"}","token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"type":"other","structure":[],"id":386},{"parent":58,"range":{"startRow":42,"endColumn":2,"startColumn":1,"endRow":42},"text":"}","token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":"↲<\/span>"},"type":"other","structure":[],"id":387},{"parent":0,"range":{"startRow":42,"endColumn":2,"startColumn":2,"endRow":42},"text":"","token":{"kind":"endOfFile","trailingTrivia":"","leadingTrivia":""},"type":"other","structure":[],"id":388}] diff --git a/Examples/Completed/errors_async/code.swift b/Examples/Completed/errors_async/code.swift new file mode 100644 index 0000000..7a081a7 --- /dev/null +++ b/Examples/Completed/errors_async/code.swift @@ -0,0 +1,23 @@ + +var vendingMachine = VendingMachine() +vendingMachine.coinsDeposited = 8 +do { + try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) + print("Success! Yum.") +} catch VendingMachineError.invalidSelection { + print("Invalid Selection.") +} catch VendingMachineError.outOfStock { + print("Out of Stock.") +} catch VendingMachineError.insufficientFunds(let coinsNeeded) { + print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.") +} catch { + print("Unexpected error: \(error).") +} + +func summarize(_ ratings: [Int]) throws(StatisticsError) { + guard !ratings.isEmpty else { throw .noRatings } +} + +async let data = fetchUserData(id: 1) +async let posts = fetchUserPosts(id: 1) +let (fetchedData, fetchedPosts) = try await (data, posts) \ No newline at end of file diff --git a/Examples/Completed/errors_async/dsl.swift b/Examples/Completed/errors_async/dsl.swift new file mode 100644 index 0000000..aad5087 --- /dev/null +++ b/Examples/Completed/errors_async/dsl.swift @@ -0,0 +1,74 @@ +Variable(.var, name: "vendingMachine", equals: Init("VendingMachine")) +Assignment("vendingMachine.coinsDeposited", Literal.integer(8)) +Do { + Call("buyFavoriteSnack") { + ParameterExp(name: "person", value: Literal.string("Alice")) + ParameterExp(name: "vendingMachine", value: Literal.ref("vendingMachine")) + }.throwing() + Call("print") { + ParameterExp(unlabeled: Literal.string("Success! Yum.")) + } +} catch: { + Catch(EnumCase("invalidSelection")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Invalid Selection.")) + } + } + Catch(EnumCase("outOfStock")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Out of Stock.")) + } + } + Catch( + EnumCase("insufficientFunds").associatedValue( + "coinsNeeded", type: "Int") + ) { + Call("print") { + ParameterExp( + unlabeled: Literal.string( + "Insufficient funds. Please insert an additional \\(coinsNeeded) coins.")) + } + } + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Unexpected error: \\(error).")) + } + } +} + +Function("summarize") { + Parameter(name: "ratings", type: "[Int]") +} _: { + Guard{ + VariableExp("ratings").property("isEmpty").not() + } else: { + Throw(EnumCase("noRatings")) + } +}.throws("StatisticsError") + +Do { + Variable(.let, name: "data") { + Call("fetchUserData") { + ParameterExp(name: "id", value: Literal.integer(1)) + } + }.async() + Variable(.let, name: "posts") { + Call("fetchUserPosts") { + ParameterExp(name: "id", value: Literal.integer(1)) + } + }.async() + TupleAssignment(["fetchedData", "fetchedPosts"], equals: Tuple { + VariableExp("data") + VariableExp("posts") + }).async().throwing() +} catch: { + Catch(EnumCase("fetchError")) { + // Example catch for async/await + } +} + + + + + + diff --git a/Examples/Completed/errors_async/syntax.json b/Examples/Completed/errors_async/syntax.json new file mode 100644 index 0000000..617a398 --- /dev/null +++ b/Examples/Completed/errors_async/syntax.json @@ -0,0 +1 @@ +[{"range":{"startRow":2,"endColumn":58,"startColumn":1,"endRow":23},"type":"other","id":0,"text":"SourceFile","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeShebang"},{"value":{"text":"nil"},"name":"shebang"},{"value":{"text":"nil"},"name":"unexpectedBetweenShebangAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndEndOfFileToken"},{"value":{"text":"","kind":"endOfFile"},"name":"endOfFileToken"},{"value":{"text":"nil"},"name":"unexpectedAfterEndOfFileToken"}]},{"range":{"startColumn":1,"endColumn":58,"startRow":2,"endRow":23},"type":"collection","id":1,"parent":0,"text":"CodeBlockItemList","structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"7"}}]},{"range":{"startColumn":1,"endColumn":38,"startRow":2,"endRow":2},"type":"other","id":2,"parent":1,"text":"CodeBlockItem","structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"VariableDeclSyntax"},"name":"item","ref":"VariableDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"range":{"startColumn":1,"endColumn":38,"startRow":2,"endRow":2},"type":"decl","id":3,"parent":2,"text":"VariableDecl","structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.var)","text":"var"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}]},{"range":{"startColumn":1,"endColumn":1,"startRow":1,"endRow":1},"type":"collection","id":4,"parent":3,"text":"AttributeList","structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"startColumn":1,"endColumn":1,"startRow":1,"endRow":1},"type":"collection","id":5,"parent":3,"text":"DeclModifierList","structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"startColumn":1,"endColumn":4,"startRow":2,"endRow":2},"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)"},"type":"other","structure":[],"id":6,"text":"var","parent":3},{"range":{"endRow":2,"startRow":2,"startColumn":5,"endColumn":38},"id":7,"text":"PatternBindingList","type":"collection","parent":3,"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endColumn":38,"startColumn":5,"endRow":2,"startRow":2},"id":8,"text":"PatternBinding","type":"other","parent":7,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"endRow":2,"startRow":2,"endColumn":19,"startColumn":5},"id":9,"text":"IdentifierPattern","type":"pattern","parent":8,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"vendingMachine","kind":"identifier("vendingMachine")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"text":"vendingMachine","parent":9,"structure":[],"type":"other","id":10,"range":{"startColumn":5,"startRow":2,"endRow":2,"endColumn":19},"token":{"kind":"identifier("vendingMachine")","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"startColumn":20,"startRow":2,"endRow":2,"endColumn":38},"id":11,"text":"InitializerClause","type":"other","parent":8,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeEqual"},{"value":{"text":"=","kind":"equal"},"name":"equal"},{"value":{"text":"nil"},"name":"unexpectedBetweenEqualAndValue"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"value"},{"value":{"text":"nil"},"name":"unexpectedAfterValue"}]},{"structure":[],"parent":11,"range":{"startColumn":20,"endRow":2,"startRow":2,"endColumn":21},"type":"other","token":{"kind":"equal","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":"=","id":12},{"range":{"startColumn":22,"endRow":2,"startRow":2,"endColumn":38},"id":13,"text":"FunctionCallExpr","type":"expr","parent":11,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"range":{"endColumn":36,"startColumn":22,"endRow":2,"startRow":2},"id":14,"text":"DeclReferenceExpr","type":"expr","parent":13,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("VendingMachine")","text":"VendingMachine"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"VendingMachine","id":15,"structure":[],"range":{"startRow":2,"endRow":2,"startColumn":22,"endColumn":36},"parent":14,"type":"other","token":{"leadingTrivia":"","kind":"identifier("VendingMachine")","trailingTrivia":""}},{"id":16,"text":"(","structure":[],"type":"other","token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"range":{"startRow":2,"endRow":2,"startColumn":36,"endColumn":37},"parent":13},{"range":{"startRow":2,"endRow":2,"startColumn":37,"endColumn":37},"id":17,"text":"LabeledExprList","type":"collection","parent":13,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"id":18,"structure":[],"range":{"endRow":2,"startRow":2,"endColumn":38,"startColumn":37},"text":")","type":"other","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"parent":13},{"range":{"endRow":2,"startRow":2,"endColumn":38,"startColumn":38},"id":19,"text":"MultipleTrailingClosureElementList","type":"collection","parent":13,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"startRow":3,"endRow":3,"startColumn":1,"endColumn":34},"id":20,"text":"CodeBlockItem","type":"other","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"InfixOperatorExprSyntax","value":{"text":"InfixOperatorExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"startRow":3,"startColumn":1,"endRow":3,"endColumn":34},"id":21,"text":"InfixOperatorExpr","type":"expr","parent":20,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftOperand"},{"ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"},"name":"leftOperand"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftOperandAndOperator"},{"ref":"AssignmentExprSyntax","value":{"text":"AssignmentExprSyntax"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndRightOperand"},{"ref":"IntegerLiteralExprSyntax","value":{"text":"IntegerLiteralExprSyntax"},"name":"rightOperand"},{"value":{"text":"nil"},"name":"unexpectedAfterRightOperand"}]},{"range":{"endColumn":30,"startRow":3,"startColumn":1,"endRow":3},"id":22,"text":"MemberAccessExpr","type":"expr","parent":21,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}]},{"range":{"startRow":3,"startColumn":1,"endRow":3,"endColumn":15},"id":23,"text":"DeclReferenceExpr","type":"expr","parent":22,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"vendingMachine","kind":"identifier("vendingMachine")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"id":24,"text":"vendingMachine","structure":[],"parent":23,"range":{"endColumn":15,"startRow":3,"startColumn":1,"endRow":3},"type":"other","token":{"leadingTrivia":"↲<\/span>","kind":"identifier("vendingMachine")","trailingTrivia":""}},{"parent":22,"text":".","id":25,"token":{"leadingTrivia":"","kind":"period","trailingTrivia":""},"structure":[],"type":"other","range":{"endColumn":16,"startRow":3,"startColumn":15,"endRow":3}},{"range":{"endColumn":30,"startRow":3,"startColumn":16,"endRow":3},"id":26,"text":"DeclReferenceExpr","type":"expr","parent":22,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"coinsDeposited","kind":"identifier("coinsDeposited")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","range":{"startRow":3,"startColumn":16,"endRow":3,"endColumn":30},"structure":[],"id":27,"text":"coinsDeposited","token":{"kind":"identifier("coinsDeposited")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":26},{"range":{"startRow":3,"startColumn":31,"endRow":3,"endColumn":32},"id":28,"text":"AssignmentExpr","type":"expr","parent":21,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedAfterEqual","value":{"text":"nil"}}]},{"id":29,"text":"=","structure":[],"parent":28,"range":{"startColumn":31,"endRow":3,"startRow":3,"endColumn":32},"type":"other","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"equal"}},{"range":{"startColumn":33,"endRow":3,"startRow":3,"endColumn":34},"id":30,"text":"IntegerLiteralExpr","type":"expr","parent":21,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLiteral"},{"value":{"text":"8","kind":"integerLiteral("8")"},"name":"literal"},{"value":{"text":"nil"},"name":"unexpectedAfterLiteral"}]},{"range":{"startRow":3,"endColumn":34,"endRow":3,"startColumn":33},"id":31,"text":"8","type":"other","parent":30,"structure":[],"token":{"trailingTrivia":"","kind":"integerLiteral("8")","leadingTrivia":""}},{"range":{"startRow":4,"endColumn":2,"endRow":15,"startColumn":1},"id":32,"text":"CodeBlockItem","type":"other","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"DoStmtSyntax","value":{"text":"DoStmtSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"endColumn":2,"endRow":15,"startColumn":1,"startRow":4},"id":33,"text":"DoStmt","type":"other","parent":32,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDoKeyword"},{"value":{"text":"do","kind":"keyword(SwiftSyntax.Keyword.do)"},"name":"doKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenDoKeywordAndThrowsClause"},{"value":{"text":"nil"},"name":"throwsClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenThrowsClauseAndBody"},{"value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax","name":"body"},{"value":{"text":"nil"},"name":"unexpectedBetweenBodyAndCatchClauses"},{"value":{"text":"CatchClauseListSyntax"},"ref":"CatchClauseListSyntax","name":"catchClauses"},{"value":{"text":"nil"},"name":"unexpectedAfterCatchClauses"}]},{"structure":[],"id":34,"type":"other","range":{"startRow":4,"endRow":4,"endColumn":3,"startColumn":1},"parent":33,"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.do)"},"text":"do"},{"range":{"startRow":4,"endRow":7,"endColumn":2,"startColumn":4},"id":35,"text":"CodeBlock","type":"other","parent":33,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"range":{"endRow":4,"startRow":4,"startColumn":4,"endColumn":5},"text":"{","parent":35,"token":{"leadingTrivia":"","kind":"leftBrace","trailingTrivia":""},"id":36,"structure":[],"type":"other"},{"range":{"endRow":6,"startRow":5,"startColumn":5,"endColumn":27},"id":37,"text":"CodeBlockItemList","type":"collection","parent":35,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}]},{"range":{"startColumn":5,"endRow":5,"endColumn":74,"startRow":5},"id":38,"text":"CodeBlockItem","type":"other","parent":37,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"TryExprSyntax"},"ref":"TryExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"startColumn":5,"endRow":5,"startRow":5,"endColumn":74},"id":39,"text":"TryExpr","type":"expr","parent":38,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeTryKeyword"},{"value":{"text":"try","kind":"keyword(SwiftSyntax.Keyword.try)"},"name":"tryKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenTryKeywordAndQuestionOrExclamationMark"},{"value":{"text":"nil"},"name":"questionOrExclamationMark"},{"value":{"text":"nil"},"name":"unexpectedBetweenQuestionOrExclamationMarkAndExpression"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}]},{"id":40,"parent":39,"type":"other","structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.try)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"text":"try","range":{"endRow":5,"startColumn":5,"startRow":5,"endColumn":8}},{"range":{"endRow":5,"startColumn":9,"startRow":5,"endColumn":74},"id":41,"text":"FunctionCallExpr","type":"expr","parent":39,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"range":{"endRow":5,"endColumn":25,"startRow":5,"startColumn":9},"id":42,"text":"DeclReferenceExpr","type":"expr","parent":41,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"buyFavoriteSnack","kind":"identifier("buyFavoriteSnack")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"structure":[],"type":"other","text":"buyFavoriteSnack","range":{"startRow":5,"startColumn":9,"endRow":5,"endColumn":25},"id":43,"parent":42,"token":{"trailingTrivia":"","kind":"identifier("buyFavoriteSnack")","leadingTrivia":""}},{"type":"other","structure":[],"parent":41,"id":44,"range":{"startRow":5,"startColumn":25,"endRow":5,"endColumn":26},"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"text":"("},{"range":{"startRow":5,"startColumn":26,"endRow":5,"endColumn":73},"id":45,"text":"LabeledExprList","type":"collection","parent":41,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"2"}}]},{"range":{"startColumn":26,"endRow":5,"endColumn":42,"startRow":5},"id":46,"text":"LabeledExpr","type":"other","parent":45,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"person","kind":"identifier("person")"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"expression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"kind":"comma","text":","},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"token":{"trailingTrivia":"","kind":"identifier("person")","leadingTrivia":""},"range":{"endRow":5,"startColumn":26,"startRow":5,"endColumn":32},"type":"other","text":"person","parent":46,"id":47,"structure":[]},{"type":"other","token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""},"structure":[],"text":":","id":48,"range":{"endRow":5,"startColumn":32,"startRow":5,"endColumn":33},"parent":46},{"range":{"endRow":5,"startColumn":34,"startRow":5,"endColumn":41},"id":49,"text":"StringLiteralExpr","type":"expr","parent":46,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}]},{"text":""","type":"other","structure":[],"parent":49,"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"range":{"startRow":5,"startColumn":34,"endRow":5,"endColumn":35},"id":50},{"range":{"startRow":5,"startColumn":35,"endRow":5,"endColumn":40},"id":51,"text":"StringLiteralSegmentList","type":"collection","parent":49,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endColumn":40,"startRow":5,"startColumn":35,"endRow":5},"id":52,"text":"StringSegment","type":"other","parent":51,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Alice","kind":"stringSegment("Alice")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"id":53,"text":"Alice","token":{"kind":"stringSegment("Alice")","leadingTrivia":"","trailingTrivia":""},"parent":52,"structure":[],"range":{"endRow":5,"endColumn":40,"startRow":5,"startColumn":35},"type":"other"},{"range":{"endRow":5,"endColumn":41,"startRow":5,"startColumn":40},"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"structure":[],"id":54,"text":""","parent":49,"type":"other"},{"structure":[],"type":"other","text":",","token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":46,"range":{"endRow":5,"endColumn":42,"startRow":5,"startColumn":41},"id":55},{"range":{"endRow":5,"endColumn":73,"startRow":5,"startColumn":43},"id":56,"text":"LabeledExpr","type":"other","parent":45,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"kind":"identifier("vendingMachine")","text":"vendingMachine"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"structure":[],"parent":56,"type":"other","token":{"kind":"identifier("vendingMachine")","trailingTrivia":"","leadingTrivia":""},"range":{"startColumn":43,"endRow":5,"startRow":5,"endColumn":57},"id":57,"text":"vendingMachine"},{"parent":56,"id":58,"text":":","token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"range":{"startColumn":57,"endRow":5,"startRow":5,"endColumn":58},"type":"other"},{"range":{"startColumn":59,"endRow":5,"startRow":5,"endColumn":73},"id":59,"text":"DeclReferenceExpr","type":"expr","parent":56,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"vendingMachine","kind":"identifier("vendingMachine")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"parent":59,"structure":[],"range":{"endRow":5,"endColumn":73,"startColumn":59,"startRow":5},"id":60,"text":"vendingMachine","token":{"kind":"identifier("vendingMachine")","leadingTrivia":"","trailingTrivia":""},"type":"other"},{"type":"other","id":61,"range":{"endRow":5,"endColumn":74,"startColumn":73,"startRow":5},"parent":41,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"text":")","structure":[]},{"range":{"endRow":5,"endColumn":74,"startColumn":74,"startRow":5},"id":62,"text":"MultipleTrailingClosureElementList","type":"collection","parent":41,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"startRow":6,"endRow":6,"endColumn":27,"startColumn":5},"id":63,"text":"CodeBlockItem","type":"other","parent":37,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"endColumn":27,"startRow":6,"startColumn":5,"endRow":6},"id":64,"text":"FunctionCallExpr","type":"expr","parent":63,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"range":{"startRow":6,"startColumn":5,"endRow":6,"endColumn":10},"id":65,"text":"DeclReferenceExpr","type":"expr","parent":64,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("print")","text":"print"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"parent":65,"structure":[],"text":"print","id":66,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("print")"},"range":{"startColumn":5,"endRow":6,"startRow":6,"endColumn":10}},{"text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"structure":[],"range":{"startColumn":10,"endRow":6,"startRow":6,"endColumn":11},"id":67,"type":"other","parent":64},{"range":{"startColumn":11,"endRow":6,"startRow":6,"endColumn":26},"id":68,"text":"LabeledExprList","type":"collection","parent":64,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startRow":6,"endRow":6,"startColumn":11,"endColumn":26},"id":69,"text":"LabeledExpr","type":"other","parent":68,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"endColumn":26,"startRow":6,"startColumn":11,"endRow":6},"id":70,"text":"StringLiteralExpr","type":"expr","parent":69,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}]},{"structure":[],"range":{"endColumn":12,"startColumn":11,"startRow":6,"endRow":6},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"id":71,"parent":70,"text":""","type":"other"},{"range":{"endColumn":25,"startColumn":12,"startRow":6,"endRow":6},"id":72,"text":"StringLiteralSegmentList","type":"collection","parent":70,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endRow":6,"endColumn":25,"startColumn":12,"startRow":6},"id":73,"text":"StringSegment","type":"other","parent":72,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Success! Yum.","kind":"stringSegment("Success! Yum.")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"type":"other","parent":73,"structure":[],"text":"Success!␣<\/span>Yum.","token":{"kind":"stringSegment("Success! Yum.")","trailingTrivia":"","leadingTrivia":""},"range":{"startRow":6,"endColumn":25,"startColumn":12,"endRow":6},"id":74},{"type":"other","text":""","structure":[],"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"parent":70,"range":{"startRow":6,"endColumn":26,"startColumn":25,"endRow":6},"id":75},{"type":"other","id":76,"range":{"startRow":6,"endColumn":27,"startColumn":26,"endRow":6},"parent":64,"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""},"structure":[],"text":")"},{"range":{"startRow":6,"endColumn":27,"startColumn":27,"endRow":6},"id":77,"text":"MultipleTrailingClosureElementList","type":"collection","parent":64,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"structure":[],"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"rightBrace"},"text":"}","range":{"endColumn":2,"endRow":7,"startRow":7,"startColumn":1},"parent":35,"id":78,"type":"other"},{"range":{"endColumn":2,"endRow":15,"startRow":7,"startColumn":3},"id":79,"text":"CatchClauseList","type":"collection","parent":33,"structure":[{"value":{"text":"CatchClauseSyntax"},"name":"Element"},{"value":{"text":"4"},"name":"Count"}]},{"range":{"endColumn":2,"startRow":7,"startColumn":3,"endRow":9},"id":80,"text":"CatchClause","type":"other","parent":79,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCatchKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.catch)","text":"catch"},"name":"catchKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenCatchKeywordAndCatchItems"},{"value":{"text":"CatchItemListSyntax"},"name":"catchItems","ref":"CatchItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCatchItemsAndBody"},{"value":{"text":"CodeBlockSyntax"},"name":"body","ref":"CodeBlockSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterBody"}]},{"id":81,"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.catch)","leadingTrivia":""},"range":{"endRow":7,"startRow":7,"startColumn":3,"endColumn":8},"type":"other","text":"catch","parent":80,"structure":[]},{"range":{"endRow":7,"startRow":7,"startColumn":9,"endColumn":45},"id":82,"text":"CatchItemList","type":"collection","parent":80,"structure":[{"value":{"text":"CatchItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endColumn":45,"startColumn":9,"startRow":7,"endRow":7},"id":83,"text":"CatchItem","type":"other","parent":82,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"startRow":7,"startColumn":9,"endRow":7,"endColumn":45},"id":84,"text":"ExpressionPattern","type":"pattern","parent":83,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"MemberAccessExprSyntax"},"name":"expression","ref":"MemberAccessExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}]},{"range":{"startRow":7,"startColumn":9,"endRow":7,"endColumn":45},"id":85,"text":"MemberAccessExpr","type":"expr","parent":84,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}]},{"range":{"startColumn":9,"endRow":7,"startRow":7,"endColumn":28},"id":86,"text":"DeclReferenceExpr","type":"expr","parent":85,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"VendingMachineError","kind":"identifier("VendingMachineError")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"token":{"kind":"identifier("VendingMachineError")","trailingTrivia":"","leadingTrivia":""},"text":"VendingMachineError","type":"other","range":{"endRow":7,"startColumn":9,"endColumn":28,"startRow":7},"id":87,"parent":86,"structure":[]},{"range":{"endRow":7,"startColumn":28,"endColumn":29,"startRow":7},"token":{"kind":"period","trailingTrivia":"","leadingTrivia":""},"text":".","structure":[],"parent":85,"type":"other","id":88},{"range":{"endRow":7,"startColumn":29,"endColumn":45,"startRow":7},"id":89,"text":"DeclReferenceExpr","type":"expr","parent":85,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"invalidSelection","kind":"identifier("invalidSelection")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"invalidSelection","structure":[],"range":{"startColumn":29,"endRow":7,"startRow":7,"endColumn":45},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("invalidSelection")"},"type":"other","parent":89,"id":90},{"range":{"startColumn":46,"endRow":9,"startRow":7,"endColumn":2},"id":91,"text":"CodeBlock","type":"other","parent":80,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"id":92,"token":{"leadingTrivia":"","kind":"leftBrace","trailingTrivia":""},"type":"other","range":{"endColumn":47,"startColumn":46,"endRow":7,"startRow":7},"parent":91,"structure":[],"text":"{"},{"range":{"endColumn":32,"startColumn":5,"endRow":8,"startRow":8},"id":93,"text":"CodeBlockItemList","type":"collection","parent":91,"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endColumn":32,"endRow":8,"startRow":8,"startColumn":5},"id":94,"text":"CodeBlockItem","type":"other","parent":93,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"startColumn":5,"endColumn":32,"startRow":8,"endRow":8},"id":95,"text":"FunctionCallExpr","type":"expr","parent":94,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"range":{"startColumn":5,"startRow":8,"endRow":8,"endColumn":10},"id":96,"text":"DeclReferenceExpr","type":"expr","parent":95,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"print","kind":"identifier("print")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"print","parent":96,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("print")"},"id":97,"range":{"endColumn":10,"startRow":8,"startColumn":5,"endRow":8},"structure":[],"type":"other"},{"text":"(","type":"other","range":{"endColumn":11,"startRow":8,"startColumn":10,"endRow":8},"parent":95,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"id":98,"structure":[]},{"range":{"endColumn":31,"startRow":8,"startColumn":11,"endRow":8},"id":99,"text":"LabeledExprList","type":"collection","parent":95,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startColumn":11,"startRow":8,"endColumn":31,"endRow":8},"id":100,"text":"LabeledExpr","type":"other","parent":99,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"endColumn":31,"endRow":8,"startColumn":11,"startRow":8},"id":101,"text":"StringLiteralExpr","type":"expr","parent":100,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}]},{"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"},"structure":[],"parent":101,"range":{"startRow":8,"startColumn":11,"endRow":8,"endColumn":12},"id":102,"text":""","type":"other"},{"range":{"startRow":8,"startColumn":12,"endRow":8,"endColumn":30},"id":103,"text":"StringLiteralSegmentList","type":"collection","parent":101,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startRow":8,"endRow":8,"startColumn":12,"endColumn":30},"id":104,"text":"StringSegment","type":"other","parent":103,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("Invalid Selection.")","text":"Invalid Selection."}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"text":"Invalid␣<\/span>Selection.","range":{"startColumn":12,"endRow":8,"startRow":8,"endColumn":30},"type":"other","structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringSegment("Invalid Selection.")"},"id":105,"parent":104},{"range":{"startColumn":30,"endRow":8,"startRow":8,"endColumn":31},"id":106,"parent":101,"structure":[],"text":""","type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"stringQuote"}},{"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"},"range":{"startColumn":31,"endRow":8,"startRow":8,"endColumn":32},"id":107,"text":")","type":"other","parent":95},{"range":{"startColumn":32,"endRow":8,"startRow":8,"endColumn":32},"id":108,"text":"MultipleTrailingClosureElementList","type":"collection","parent":95,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"id":109,"range":{"endRow":9,"endColumn":2,"startColumn":1,"startRow":9},"type":"other","parent":91,"token":{"trailingTrivia":"␣<\/span>","kind":"rightBrace","leadingTrivia":"↲<\/span>"},"structure":[],"text":"}"},{"range":{"endRow":11,"endColumn":2,"startColumn":3,"startRow":9},"id":110,"text":"CatchClause","type":"other","parent":79,"structure":[{"name":"unexpectedBeforeCatchKeyword","value":{"text":"nil"}},{"name":"catchKeyword","value":{"text":"catch","kind":"keyword(SwiftSyntax.Keyword.catch)"}},{"name":"unexpectedBetweenCatchKeywordAndCatchItems","value":{"text":"nil"}},{"name":"catchItems","ref":"CatchItemListSyntax","value":{"text":"CatchItemListSyntax"}},{"name":"unexpectedBetweenCatchItemsAndBody","value":{"text":"nil"}},{"name":"body","ref":"CodeBlockSyntax","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}]},{"type":"other","parent":110,"structure":[],"range":{"startColumn":3,"startRow":9,"endColumn":8,"endRow":9},"id":111,"token":{"kind":"keyword(SwiftSyntax.Keyword.catch)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"text":"catch"},{"range":{"startColumn":9,"startRow":9,"endColumn":39,"endRow":9},"id":112,"text":"CatchItemList","type":"collection","parent":110,"structure":[{"name":"Element","value":{"text":"CatchItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startColumn":9,"endColumn":39,"startRow":9,"endRow":9},"id":113,"text":"CatchItem","type":"other","parent":112,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"ExpressionPatternSyntax"},"name":"pattern","ref":"ExpressionPatternSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"startRow":9,"startColumn":9,"endRow":9,"endColumn":39},"id":114,"text":"ExpressionPattern","type":"pattern","parent":113,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"MemberAccessExprSyntax"},"name":"expression","ref":"MemberAccessExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}]},{"range":{"endColumn":39,"startColumn":9,"startRow":9,"endRow":9},"id":115,"text":"MemberAccessExpr","type":"expr","parent":114,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}]},{"range":{"startRow":9,"startColumn":9,"endColumn":28,"endRow":9},"id":116,"text":"DeclReferenceExpr","type":"expr","parent":115,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"VendingMachineError","kind":"identifier("VendingMachineError")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"VendingMachineError","id":117,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("VendingMachineError")"},"parent":116,"type":"other","range":{"endRow":9,"endColumn":28,"startColumn":9,"startRow":9},"structure":[]},{"id":118,"structure":[],"range":{"endRow":9,"endColumn":29,"startColumn":28,"startRow":9},"text":".","parent":115,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"period"}},{"range":{"endRow":9,"endColumn":39,"startColumn":29,"startRow":9},"id":119,"text":"DeclReferenceExpr","type":"expr","parent":115,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"outOfStock","kind":"identifier("outOfStock")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"outOfStock","range":{"startRow":9,"endColumn":39,"endRow":9,"startColumn":29},"parent":119,"id":120,"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("outOfStock")","leadingTrivia":""},"structure":[],"type":"other"},{"range":{"startRow":9,"endColumn":2,"endRow":11,"startColumn":40},"id":121,"text":"CodeBlock","type":"other","parent":110,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"parent":121,"type":"other","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"startColumn":40,"endRow":9,"startRow":9,"endColumn":41},"id":122,"text":"{"},{"range":{"startColumn":5,"endRow":10,"startRow":10,"endColumn":27},"id":123,"text":"CodeBlockItemList","type":"collection","parent":121,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startRow":10,"startColumn":5,"endRow":10,"endColumn":27},"id":124,"text":"CodeBlockItem","type":"other","parent":123,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"endColumn":27,"startRow":10,"endRow":10,"startColumn":5},"id":125,"text":"FunctionCallExpr","type":"expr","parent":124,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"range":{"startColumn":5,"endRow":10,"endColumn":10,"startRow":10},"id":126,"text":"DeclReferenceExpr","type":"expr","parent":125,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","text":"print","parent":126,"id":127,"token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"range":{"startRow":10,"endColumn":10,"startColumn":5,"endRow":10}},{"text":"(","parent":125,"type":"other","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"startRow":10,"endColumn":11,"startColumn":10,"endRow":10},"id":128,"structure":[]},{"range":{"startRow":10,"endColumn":26,"startColumn":11,"endRow":10},"id":129,"text":"LabeledExprList","type":"collection","parent":125,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"startColumn":11,"endRow":10,"startRow":10,"endColumn":26},"id":130,"text":"LabeledExpr","type":"other","parent":129,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"endRow":10,"startRow":10,"endColumn":26,"startColumn":11},"id":131,"text":"StringLiteralExpr","type":"expr","parent":130,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments","ref":"StringLiteralSegmentListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}]},{"range":{"startColumn":11,"endColumn":12,"endRow":10,"startRow":10},"id":132,"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"parent":131,"type":"other","structure":[]},{"range":{"startColumn":12,"endColumn":25,"endRow":10,"startRow":10},"id":133,"text":"StringLiteralSegmentList","type":"collection","parent":131,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"startColumn":12,"endRow":10,"startRow":10,"endColumn":25},"id":134,"text":"StringSegment","type":"other","parent":133,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"Out of Stock.","kind":"stringSegment("Out of Stock.")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"parent":134,"id":135,"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringSegment("Out of Stock.")"},"range":{"endRow":10,"startRow":10,"endColumn":25,"startColumn":12},"text":"Out␣<\/span>of␣<\/span>Stock.","type":"other"},{"text":""","id":136,"range":{"endRow":10,"startRow":10,"endColumn":26,"startColumn":25},"type":"other","structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"stringQuote"},"parent":131},{"structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"rightParen"},"range":{"endRow":10,"startRow":10,"endColumn":27,"startColumn":26},"id":137,"text":")","type":"other","parent":125},{"range":{"endRow":10,"startRow":10,"endColumn":27,"startColumn":27},"id":138,"text":"MultipleTrailingClosureElementList","type":"collection","parent":125,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"text":"}","id":139,"parent":121,"structure":[],"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"rightBrace"},"type":"other","range":{"endRow":11,"startRow":11,"startColumn":1,"endColumn":2}},{"range":{"endRow":13,"startRow":11,"startColumn":3,"endColumn":2},"id":140,"text":"CatchClause","type":"other","parent":79,"structure":[{"name":"unexpectedBeforeCatchKeyword","value":{"text":"nil"}},{"name":"catchKeyword","value":{"text":"catch","kind":"keyword(SwiftSyntax.Keyword.catch)"}},{"name":"unexpectedBetweenCatchKeywordAndCatchItems","value":{"text":"nil"}},{"name":"catchItems","value":{"text":"CatchItemListSyntax"},"ref":"CatchItemListSyntax"},{"name":"unexpectedBetweenCatchItemsAndBody","value":{"text":"nil"}},{"name":"body","value":{"text":"CodeBlockSyntax"},"ref":"CodeBlockSyntax"},{"name":"unexpectedAfterBody","value":{"text":"nil"}}]},{"parent":140,"type":"other","text":"catch","structure":[],"range":{"endColumn":8,"endRow":11,"startColumn":3,"startRow":11},"id":141,"token":{"kind":"keyword(SwiftSyntax.Keyword.catch)","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"endColumn":63,"endRow":11,"startColumn":9,"startRow":11},"id":142,"text":"CatchItemList","type":"collection","parent":140,"structure":[{"value":{"text":"CatchItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endRow":11,"startColumn":9,"endColumn":63,"startRow":11},"id":143,"text":"CatchItem","type":"other","parent":142,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"ExpressionPatternSyntax","value":{"text":"ExpressionPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndWhereClause"},{"value":{"text":"nil"},"name":"whereClause"},{"value":{"text":"nil"},"name":"unexpectedBetweenWhereClauseAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"startColumn":9,"startRow":11,"endRow":11,"endColumn":63},"id":144,"text":"ExpressionPattern","type":"pattern","parent":143,"structure":[{"name":"unexpectedBeforeExpression","value":{"text":"nil"}},{"name":"expression","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"range":{"startColumn":9,"endRow":11,"endColumn":63,"startRow":11},"id":145,"text":"FunctionCallExpr","type":"expr","parent":144,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"range":{"startRow":11,"endRow":11,"endColumn":46,"startColumn":9},"id":146,"text":"MemberAccessExpr","type":"expr","parent":145,"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"base","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}]},{"range":{"startRow":11,"startColumn":9,"endColumn":28,"endRow":11},"id":147,"text":"DeclReferenceExpr","type":"expr","parent":146,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"VendingMachineError","kind":"identifier("VendingMachineError")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"text":"VendingMachineError","structure":[],"parent":147,"id":148,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("VendingMachineError")"},"range":{"endColumn":28,"startRow":11,"startColumn":9,"endRow":11},"type":"other"},{"structure":[],"id":149,"text":".","range":{"endColumn":29,"startRow":11,"startColumn":28,"endRow":11},"type":"other","parent":146,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"period"}},{"range":{"endColumn":46,"startRow":11,"startColumn":29,"endRow":11},"id":150,"text":"DeclReferenceExpr","type":"expr","parent":146,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("insufficientFunds")","text":"insufficientFunds"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"token":{"trailingTrivia":"","kind":"identifier("insufficientFunds")","leadingTrivia":""},"parent":150,"type":"other","structure":[],"id":151,"range":{"startColumn":29,"endRow":11,"endColumn":46,"startRow":11},"text":"insufficientFunds"},{"parent":145,"id":152,"text":"(","structure":[],"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"startColumn":46,"endRow":11,"endColumn":47,"startRow":11},"type":"other"},{"range":{"startColumn":47,"endRow":11,"endColumn":62,"startRow":11},"id":153,"text":"LabeledExprList","type":"collection","parent":145,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startRow":11,"endRow":11,"startColumn":47,"endColumn":62},"id":154,"text":"LabeledExpr","type":"other","parent":153,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"PatternExprSyntax"},"ref":"PatternExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startRow":11,"startColumn":47,"endRow":11,"endColumn":62},"id":155,"text":"PatternExpr","type":"expr","parent":154,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"ValueBindingPatternSyntax","name":"pattern","value":{"text":"ValueBindingPatternSyntax"}},{"name":"unexpectedAfterPattern","value":{"text":"nil"}}]},{"range":{"endRow":11,"startRow":11,"startColumn":47,"endColumn":62},"id":156,"text":"ValueBindingPattern","type":"pattern","parent":155,"structure":[{"name":"unexpectedBeforeBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndPattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedAfterPattern","value":{"text":"nil"}}]},{"id":157,"type":"other","parent":156,"range":{"endColumn":50,"endRow":11,"startColumn":47,"startRow":11},"text":"let","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":""},"structure":[]},{"range":{"endColumn":62,"endRow":11,"startColumn":51,"startRow":11},"id":158,"text":"IdentifierPattern","type":"pattern","parent":156,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"coinsNeeded","kind":"identifier("coinsNeeded")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"id":159,"text":"coinsNeeded","parent":158,"range":{"endColumn":62,"startRow":11,"endRow":11,"startColumn":51},"structure":[],"token":{"kind":"identifier("coinsNeeded")","leadingTrivia":"","trailingTrivia":""},"type":"other"},{"parent":145,"range":{"endColumn":63,"startRow":11,"endRow":11,"startColumn":62},"text":")","id":160,"type":"other","structure":[],"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"range":{"endColumn":64,"startRow":11,"endRow":11,"startColumn":64},"id":161,"text":"MultipleTrailingClosureElementList","type":"collection","parent":145,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"endColumn":2,"startColumn":64,"startRow":11,"endRow":13},"id":162,"text":"CodeBlock","type":"other","parent":140,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}]},{"id":163,"type":"other","structure":[],"text":"{","range":{"endRow":11,"startRow":11,"startColumn":64,"endColumn":65},"parent":162,"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""}},{"range":{"endRow":12,"startRow":12,"startColumn":5,"endColumn":83},"id":164,"text":"CodeBlockItemList","type":"collection","parent":162,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startRow":12,"endColumn":83,"endRow":12,"startColumn":5},"id":165,"text":"CodeBlockItem","type":"other","parent":164,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"endColumn":83,"endRow":12,"startRow":12,"startColumn":5},"id":166,"text":"FunctionCallExpr","type":"expr","parent":165,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"range":{"endRow":12,"endColumn":10,"startColumn":5,"startRow":12},"id":167,"text":"DeclReferenceExpr","type":"expr","parent":166,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"token":{"kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"type":"other","text":"print","parent":167,"id":168,"range":{"endColumn":10,"startColumn":5,"endRow":12,"startRow":12},"structure":[]},{"type":"other","parent":166,"text":"(","range":{"endColumn":11,"startColumn":10,"endRow":12,"startRow":12},"id":169,"structure":[],"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""}},{"range":{"endColumn":82,"startColumn":11,"endRow":12,"startRow":12},"id":170,"text":"LabeledExprList","type":"collection","parent":166,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endColumn":82,"endRow":12,"startRow":12,"startColumn":11},"id":171,"text":"LabeledExpr","type":"other","parent":170,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"endColumn":82,"startColumn":11,"startRow":12,"endRow":12},"id":172,"text":"StringLiteralExpr","type":"expr","parent":171,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments","ref":"StringLiteralSegmentListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}]},{"range":{"startRow":12,"endColumn":12,"startColumn":11,"endRow":12},"type":"other","text":""","structure":[],"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"id":173,"parent":172},{"range":{"startRow":12,"endColumn":81,"startColumn":12,"endRow":12},"id":174,"text":"StringLiteralSegmentList","type":"collection","parent":172,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"3"}}]},{"range":{"endRow":12,"startRow":12,"startColumn":12,"endColumn":60},"id":175,"text":"StringSegment","type":"other","parent":174,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Insufficient funds. Please insert an additional ")","text":"Insufficient funds. Please insert an additional "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"token":{"trailingTrivia":"","kind":"stringSegment("Insufficient funds. Please insert an additional ")","leadingTrivia":""},"structure":[],"text":"Insufficient␣<\/span>funds.␣<\/span>Please␣<\/span>insert␣<\/span>an␣<\/span>additional␣<\/span>","type":"other","id":176,"range":{"endRow":12,"endColumn":60,"startRow":12,"startColumn":12},"parent":175},{"range":{"endRow":12,"endColumn":74,"startRow":12,"startColumn":60},"id":177,"text":"ExpressionSegment","type":"other","parent":174,"structure":[{"name":"unexpectedBeforeBackslash","value":{"text":"nil"}},{"name":"backslash","value":{"text":"\\","kind":"backslash"}},{"name":"unexpectedBetweenBackslashAndPounds","value":{"text":"nil"}},{"name":"pounds","value":{"text":"nil"}},{"name":"unexpectedBetweenPoundsAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndExpressions","value":{"text":"nil"}},{"name":"expressions","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenExpressionsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"text":"\\","type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"backslash"},"structure":[],"id":178,"range":{"startColumn":60,"endRow":12,"endColumn":61,"startRow":12},"parent":177},{"range":{"startColumn":61,"endRow":12,"endColumn":62,"startRow":12},"parent":177,"type":"other","structure":[],"text":"(","id":179,"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"}},{"range":{"startColumn":62,"endRow":12,"endColumn":73,"startRow":12},"id":180,"text":"LabeledExprList","type":"collection","parent":177,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"startRow":12,"endRow":12,"endColumn":73,"startColumn":62},"id":181,"text":"LabeledExpr","type":"other","parent":180,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startRow":12,"endColumn":73,"startColumn":62,"endRow":12},"id":182,"text":"DeclReferenceExpr","type":"expr","parent":181,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"coinsNeeded","kind":"identifier("coinsNeeded")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"id":183,"parent":182,"text":"coinsNeeded","range":{"startColumn":62,"endRow":12,"endColumn":73,"startRow":12},"token":{"trailingTrivia":"","kind":"identifier("coinsNeeded")","leadingTrivia":""},"type":"other","structure":[]},{"id":184,"token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"text":")","range":{"startColumn":73,"endRow":12,"endColumn":74,"startRow":12},"parent":177,"structure":[],"type":"other"},{"range":{"startColumn":74,"endRow":12,"endColumn":81,"startRow":12},"id":185,"text":"StringSegment","type":"other","parent":174,"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment(" coins.")","text":" coins."}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}]},{"parent":185,"id":186,"type":"other","range":{"endRow":12,"endColumn":81,"startColumn":74,"startRow":12},"text":"␣<\/span>coins.","structure":[],"token":{"kind":"stringSegment(" coins.")","leadingTrivia":"","trailingTrivia":""}},{"text":""","id":187,"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"type":"other","range":{"endRow":12,"endColumn":82,"startColumn":81,"startRow":12},"structure":[],"parent":172},{"type":"other","parent":166,"structure":[],"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"text":")","range":{"endRow":12,"endColumn":83,"startColumn":82,"startRow":12},"id":188},{"range":{"endRow":12,"endColumn":83,"startColumn":83,"startRow":12},"id":189,"text":"MultipleTrailingClosureElementList","type":"collection","parent":166,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"parent":162,"structure":[],"id":190,"text":"}","type":"other","range":{"startColumn":1,"endRow":13,"startRow":13,"endColumn":2},"token":{"leadingTrivia":"↲<\/span>","kind":"rightBrace","trailingTrivia":"␣<\/span>"}},{"range":{"startColumn":3,"endRow":15,"startRow":13,"endColumn":2},"id":191,"text":"CatchClause","type":"other","parent":79,"structure":[{"name":"unexpectedBeforeCatchKeyword","value":{"text":"nil"}},{"name":"catchKeyword","value":{"text":"catch","kind":"keyword(SwiftSyntax.Keyword.catch)"}},{"name":"unexpectedBetweenCatchKeywordAndCatchItems","value":{"text":"nil"}},{"ref":"CatchItemListSyntax","name":"catchItems","value":{"text":"CatchItemListSyntax"}},{"name":"unexpectedBetweenCatchItemsAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}]},{"id":192,"token":{"kind":"keyword(SwiftSyntax.Keyword.catch)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":8,"startColumn":3,"endRow":13,"startRow":13},"structure":[],"type":"other","text":"catch","parent":191},{"range":{"endColumn":9,"startColumn":9,"endRow":13,"startRow":13},"id":193,"text":"CatchItemList","type":"collection","parent":191,"structure":[{"value":{"text":"CatchItemSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"startRow":13,"endRow":15,"startColumn":9,"endColumn":2},"id":194,"text":"CodeBlock","type":"other","parent":191,"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"text":"{","kind":"leftBrace"}},{"name":"unexpectedBetweenLeftBraceAndStatements","value":{"text":"nil"}},{"name":"statements","value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax"},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"kind":"rightBrace","text":"}"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}]},{"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"id":195,"type":"other","structure":[],"range":{"startColumn":9,"endRow":13,"startRow":13,"endColumn":10},"text":"{","parent":194},{"range":{"startColumn":5,"endRow":14,"startRow":14,"endColumn":41},"id":196,"text":"CodeBlockItemList","type":"collection","parent":194,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startRow":14,"startColumn":5,"endRow":14,"endColumn":41},"id":197,"text":"CodeBlockItem","type":"other","parent":196,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"endColumn":41,"startColumn":5,"endRow":14,"startRow":14},"id":198,"text":"FunctionCallExpr","type":"expr","parent":197,"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}]},{"range":{"startRow":14,"startColumn":5,"endRow":14,"endColumn":10},"id":199,"text":"DeclReferenceExpr","type":"expr","parent":198,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"print","kind":"identifier("print")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"parent":199,"id":200,"token":{"trailingTrivia":"","kind":"identifier("print")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"structure":[],"range":{"endColumn":10,"startRow":14,"startColumn":5,"endRow":14},"text":"print","type":"other"},{"parent":198,"text":"(","structure":[],"range":{"endColumn":11,"startRow":14,"startColumn":10,"endRow":14},"type":"other","id":201,"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""}},{"range":{"endColumn":40,"startRow":14,"startColumn":11,"endRow":14},"id":202,"text":"LabeledExprList","type":"collection","parent":198,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"startRow":14,"endRow":14,"endColumn":40,"startColumn":11},"id":203,"text":"LabeledExpr","type":"other","parent":202,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"StringLiteralExprSyntax","name":"expression","value":{"text":"StringLiteralExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startRow":14,"endColumn":40,"endRow":14,"startColumn":11},"id":204,"text":"StringLiteralExpr","type":"expr","parent":203,"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"ref":"StringLiteralSegmentListSyntax","name":"segments","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}]},{"id":205,"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"range":{"endRow":14,"startRow":14,"startColumn":11,"endColumn":12},"text":""","structure":[],"type":"other","parent":204},{"range":{"endRow":14,"startRow":14,"startColumn":12,"endColumn":39},"id":206,"text":"StringLiteralSegmentList","type":"collection","parent":204,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}]},{"range":{"endRow":14,"endColumn":30,"startRow":14,"startColumn":12},"id":207,"text":"StringSegment","type":"other","parent":206,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("Unexpected error: ")","text":"Unexpected error: "},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"type":"other","text":"Unexpected␣<\/span>error:␣<\/span>","id":208,"parent":207,"structure":[],"range":{"endRow":14,"startColumn":12,"endColumn":30,"startRow":14},"token":{"leadingTrivia":"","kind":"stringSegment("Unexpected error: ")","trailingTrivia":""}},{"range":{"endRow":14,"startColumn":30,"endColumn":38,"startRow":14},"id":209,"text":"ExpressionSegment","type":"other","parent":206,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBackslash"},{"value":{"text":"\\","kind":"backslash"},"name":"backslash"},{"value":{"text":"nil"},"name":"unexpectedBetweenBackslashAndPounds"},{"value":{"text":"nil"},"name":"pounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenPoundsAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndExpressions"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"expressions"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}]},{"parent":209,"type":"other","structure":[],"range":{"endColumn":31,"startRow":14,"startColumn":30,"endRow":14},"token":{"kind":"backslash","trailingTrivia":"","leadingTrivia":""},"text":"\\","id":210},{"structure":[],"token":{"kind":"leftParen","trailingTrivia":"","leadingTrivia":""},"id":211,"type":"other","range":{"endColumn":32,"startRow":14,"startColumn":31,"endRow":14},"parent":209,"text":"("},{"range":{"endColumn":37,"startRow":14,"startColumn":32,"endRow":14},"id":212,"text":"LabeledExprList","type":"collection","parent":209,"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endRow":14,"startColumn":32,"startRow":14,"endColumn":37},"id":213,"text":"LabeledExpr","type":"other","parent":212,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"endRow":14,"startColumn":32,"startRow":14,"endColumn":37},"id":214,"text":"DeclReferenceExpr","type":"expr","parent":213,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("error")","text":"error"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"token":{"kind":"identifier("error")","trailingTrivia":"","leadingTrivia":""},"structure":[],"range":{"endRow":14,"startColumn":32,"endColumn":37,"startRow":14},"text":"error","parent":214,"type":"other","id":215},{"range":{"endRow":14,"startColumn":37,"endColumn":38,"startRow":14},"parent":209,"id":216,"text":")","structure":[],"type":"other","token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""}},{"range":{"endRow":14,"startColumn":38,"endColumn":39,"startRow":14},"id":217,"text":"StringSegment","type":"other","parent":206,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"text":".","kind":"stringSegment(".")"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}]},{"token":{"trailingTrivia":"","kind":"stringSegment(".")","leadingTrivia":""},"range":{"startRow":14,"startColumn":38,"endRow":14,"endColumn":39},"parent":217,"structure":[],"type":"other","id":218,"text":"."},{"text":""","token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""},"type":"other","structure":[],"parent":204,"range":{"startRow":14,"startColumn":39,"endRow":14,"endColumn":40},"id":219},{"id":220,"token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"range":{"startRow":14,"startColumn":40,"endRow":14,"endColumn":41},"type":"other","parent":198,"text":")","structure":[]},{"range":{"startRow":14,"startColumn":41,"endRow":14,"endColumn":41},"id":221,"text":"MultipleTrailingClosureElementList","type":"collection","parent":198,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"startRow":15,"endColumn":2,"endRow":15,"startColumn":1},"text":"}","structure":[],"type":"other","token":{"leadingTrivia":"↲<\/span>","kind":"rightBrace","trailingTrivia":""},"id":222,"parent":194},{"range":{"startRow":17,"endColumn":2,"endRow":19,"startColumn":1},"id":223,"text":"CodeBlockItem","type":"other","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"FunctionDeclSyntax","value":{"text":"FunctionDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"endColumn":2,"startRow":17,"startColumn":1,"endRow":19},"id":224,"text":"FunctionDecl","type":"decl","parent":223,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFuncKeyword","value":{"text":"nil"}},{"name":"funcKeyword","value":{"text":"func","kind":"keyword(SwiftSyntax.Keyword.func)"}},{"name":"unexpectedBetweenFuncKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("summarize")","text":"summarize"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndSignature","value":{"text":"nil"}},{"ref":"FunctionSignatureSyntax","name":"signature","value":{"text":"FunctionSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}]},{"range":{"startRow":15,"startColumn":2,"endColumn":2,"endRow":15},"id":225,"text":"AttributeList","type":"collection","parent":224,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"startRow":15,"startColumn":2,"endColumn":2,"endRow":15},"id":226,"text":"DeclModifierList","type":"collection","parent":224,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"token":{"leadingTrivia":"↲<\/span>↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.func)"},"range":{"endColumn":5,"startColumn":1,"endRow":17,"startRow":17},"text":"func","type":"other","parent":224,"structure":[],"id":227},{"parent":224,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("summarize")"},"id":228,"text":"summarize","type":"other","range":{"endColumn":15,"startColumn":6,"endRow":17,"startRow":17}},{"range":{"endColumn":57,"startColumn":15,"endRow":17,"startRow":17},"id":229,"text":"FunctionSignature","type":"other","parent":224,"structure":[{"name":"unexpectedBeforeParameterClause","value":{"text":"nil"}},{"ref":"FunctionParameterClauseSyntax","name":"parameterClause","value":{"text":"FunctionParameterClauseSyntax"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"ref":"FunctionEffectSpecifiersSyntax","name":"effectSpecifiers","value":{"text":"FunctionEffectSpecifiersSyntax"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}]},{"range":{"startColumn":15,"endRow":17,"startRow":17,"endColumn":33},"id":230,"text":"FunctionParameterClause","type":"other","parent":229,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"ref":"FunctionParameterListSyntax","name":"parameters","value":{"text":"FunctionParameterListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"structure":[],"type":"other","id":231,"text":"(","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"range":{"endColumn":16,"startRow":17,"startColumn":15,"endRow":17},"parent":230},{"range":{"endColumn":32,"startRow":17,"startColumn":16,"endRow":17},"id":232,"text":"FunctionParameterList","type":"collection","parent":230,"structure":[{"name":"Element","value":{"text":"FunctionParameterSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endColumn":32,"startColumn":16,"startRow":17,"endRow":17},"id":233,"text":"FunctionParameter","type":"other","parent":232,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndFirstName","value":{"text":"nil"}},{"name":"firstName","value":{"kind":"wildcard","text":"_"}},{"name":"unexpectedBetweenFirstNameAndSecondName","value":{"text":"nil"}},{"name":"secondName","value":{"text":"ratings","kind":"identifier("ratings")"}},{"name":"unexpectedBetweenSecondNameAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","ref":"ArrayTypeSyntax","value":{"text":"ArrayTypeSyntax"}},{"name":"unexpectedBetweenTypeAndEllipsis","value":{"text":"nil"}},{"name":"ellipsis","value":{"text":"nil"}},{"name":"unexpectedBetweenEllipsisAndDefaultValue","value":{"text":"nil"}},{"name":"defaultValue","value":{"text":"nil"}},{"name":"unexpectedBetweenDefaultValueAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startRow":17,"endRow":17,"endColumn":16,"startColumn":16},"id":234,"text":"AttributeList","type":"collection","parent":233,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"startColumn":16,"endColumn":16,"endRow":17,"startRow":17},"id":235,"text":"DeclModifierList","type":"collection","parent":233,"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"wildcard"},"type":"other","range":{"startRow":17,"startColumn":16,"endRow":17,"endColumn":17},"parent":233,"text":"_","id":236},{"id":237,"parent":233,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("ratings")"},"text":"ratings","range":{"startRow":17,"startColumn":18,"endRow":17,"endColumn":25},"type":"other"},{"parent":233,"structure":[],"id":238,"text":":","range":{"startRow":17,"startColumn":25,"endRow":17,"endColumn":26},"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"type":"other"},{"range":{"startRow":17,"startColumn":27,"endRow":17,"endColumn":32},"id":239,"text":"ArrayType","type":"type","parent":233,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftSquare"},{"value":{"kind":"leftSquare","text":"["},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndElement"},{"value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax","name":"element"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedAfterRightSquare"}]},{"id":240,"type":"other","structure":[],"range":{"startRow":17,"endRow":17,"endColumn":28,"startColumn":27},"text":"[","parent":239,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftSquare"}},{"range":{"startRow":17,"endRow":17,"endColumn":31,"startColumn":28},"id":241,"text":"IdentifierType","type":"type","parent":239,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Int","kind":"identifier("Int")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}]},{"text":"Int","type":"other","parent":241,"token":{"kind":"identifier("Int")","trailingTrivia":"","leadingTrivia":""},"id":242,"range":{"endRow":17,"startRow":17,"endColumn":31,"startColumn":28},"structure":[]},{"range":{"endRow":17,"startRow":17,"endColumn":32,"startColumn":31},"parent":239,"token":{"kind":"rightSquare","trailingTrivia":"","leadingTrivia":""},"structure":[],"id":243,"text":"]","type":"other"},{"id":244,"structure":[],"token":{"kind":"rightParen","trailingTrivia":"␣<\/span>","leadingTrivia":""},"text":")","type":"other","range":{"endRow":17,"startRow":17,"endColumn":33,"startColumn":32},"parent":230},{"range":{"endRow":17,"startRow":17,"endColumn":57,"startColumn":34},"id":245,"text":"FunctionEffectSpecifiers","type":"other","parent":229,"structure":[{"name":"unexpectedBeforeAsyncSpecifier","value":{"text":"nil"}},{"name":"asyncSpecifier","value":{"text":"nil"}},{"name":"unexpectedBetweenAsyncSpecifierAndThrowsClause","value":{"text":"nil"}},{"name":"throwsClause","value":{"text":"ThrowsClauseSyntax"},"ref":"ThrowsClauseSyntax"},{"name":"unexpectedAfterThrowsClause","value":{"text":"nil"}}]},{"range":{"startRow":17,"endRow":17,"endColumn":57,"startColumn":34},"id":246,"text":"ThrowsClause","type":"other","parent":245,"structure":[{"name":"unexpectedBeforeThrowsSpecifier","value":{"text":"nil"}},{"name":"throwsSpecifier","value":{"text":"throws","kind":"keyword(SwiftSyntax.Keyword.throws)"}},{"name":"unexpectedBetweenThrowsSpecifierAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndType","value":{"text":"nil"}},{"ref":"IdentifierTypeSyntax","name":"type","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenTypeAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"range":{"endColumn":40,"startColumn":34,"startRow":17,"endRow":17},"parent":246,"token":{"kind":"keyword(SwiftSyntax.Keyword.throws)","leadingTrivia":"","trailingTrivia":""},"text":"throws","type":"other","id":247,"structure":[]},{"id":248,"range":{"endColumn":41,"startColumn":40,"startRow":17,"endRow":17},"parent":246,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"(","type":"other"},{"range":{"endColumn":56,"startColumn":41,"startRow":17,"endRow":17},"id":249,"text":"IdentifierType","type":"type","parent":246,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"StatisticsError","kind":"identifier("StatisticsError")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}]},{"type":"other","range":{"startColumn":41,"endColumn":56,"endRow":17,"startRow":17},"id":250,"parent":249,"token":{"kind":"identifier("StatisticsError")","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"StatisticsError"},{"type":"other","range":{"startColumn":56,"endColumn":57,"endRow":17,"startRow":17},"parent":246,"token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"structure":[],"id":251,"text":")"},{"range":{"startColumn":58,"endColumn":2,"endRow":19,"startRow":17},"id":252,"text":"CodeBlock","type":"other","parent":224,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"id":253,"parent":252,"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"range":{"endRow":17,"endColumn":59,"startRow":17,"startColumn":58},"text":"{","structure":[],"type":"other"},{"range":{"endRow":18,"endColumn":53,"startRow":18,"startColumn":5},"id":254,"text":"CodeBlockItemList","type":"collection","parent":252,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endRow":18,"startRow":18,"endColumn":53,"startColumn":5},"id":255,"text":"CodeBlockItem","type":"other","parent":254,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"GuardStmtSyntax"},"ref":"GuardStmtSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"range":{"endColumn":53,"endRow":18,"startRow":18,"startColumn":5},"id":256,"text":"GuardStmt","type":"other","parent":255,"structure":[{"name":"unexpectedBeforeGuardKeyword","value":{"text":"nil"}},{"name":"guardKeyword","value":{"text":"guard","kind":"keyword(SwiftSyntax.Keyword.guard)"}},{"name":"unexpectedBetweenGuardKeywordAndConditions","value":{"text":"nil"}},{"ref":"ConditionElementListSyntax","name":"conditions","value":{"text":"ConditionElementListSyntax"}},{"name":"unexpectedBetweenConditionsAndElseKeyword","value":{"text":"nil"}},{"name":"elseKeyword","value":{"text":"else","kind":"keyword(SwiftSyntax.Keyword.else)"}},{"name":"unexpectedBetweenElseKeywordAndBody","value":{"text":"nil"}},{"ref":"CodeBlockSyntax","name":"body","value":{"text":"CodeBlockSyntax"}},{"name":"unexpectedAfterBody","value":{"text":"nil"}}]},{"range":{"startRow":18,"endColumn":10,"endRow":18,"startColumn":5},"parent":256,"id":257,"structure":[],"text":"guard","token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.guard)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"type":"other"},{"range":{"startRow":18,"endColumn":27,"endRow":18,"startColumn":11},"id":258,"text":"ConditionElementList","type":"collection","parent":256,"structure":[{"name":"Element","value":{"text":"ConditionElementSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"startColumn":11,"endColumn":27,"startRow":18,"endRow":18},"id":259,"text":"ConditionElement","type":"other","parent":258,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"value":{"text":"PrefixOperatorExprSyntax"},"ref":"PrefixOperatorExprSyntax","name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"endRow":18,"startRow":18,"startColumn":11,"endColumn":27},"id":260,"text":"PrefixOperatorExpr","type":"expr","parent":259,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOperator"},{"value":{"kind":"prefixOperator("!")","text":"!"},"name":"operator"},{"value":{"text":"nil"},"name":"unexpectedBetweenOperatorAndExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedAfterExpression"}]},{"token":{"trailingTrivia":"","leadingTrivia":"","kind":"prefixOperator("!")"},"type":"other","range":{"startRow":18,"endRow":18,"startColumn":11,"endColumn":12},"text":"!","id":261,"structure":[],"parent":260},{"range":{"startRow":18,"endRow":18,"startColumn":12,"endColumn":27},"id":262,"text":"MemberAccessExpr","type":"expr","parent":260,"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}]},{"range":{"startRow":18,"endRow":18,"startColumn":12,"endColumn":19},"id":263,"text":"DeclReferenceExpr","type":"expr","parent":262,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("ratings")","text":"ratings"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"type":"other","parent":263,"token":{"kind":"identifier("ratings")","trailingTrivia":"","leadingTrivia":""},"text":"ratings","range":{"startRow":18,"endColumn":19,"startColumn":12,"endRow":18},"id":264,"structure":[]},{"type":"other","id":265,"text":".","parent":262,"token":{"kind":"period","trailingTrivia":"","leadingTrivia":""},"structure":[],"range":{"startRow":18,"endColumn":20,"startColumn":19,"endRow":18}},{"range":{"startRow":18,"endColumn":27,"startColumn":20,"endRow":18},"id":266,"text":"DeclReferenceExpr","type":"expr","parent":262,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"isEmpty","kind":"identifier("isEmpty")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"text":"isEmpty","parent":266,"token":{"kind":"identifier("isEmpty")","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":18,"endRow":18,"startColumn":20,"endColumn":27},"type":"other","structure":[],"id":267},{"range":{"startRow":18,"endRow":18,"startColumn":28,"endColumn":32},"parent":256,"type":"other","structure":[],"id":268,"text":"else","token":{"kind":"keyword(SwiftSyntax.Keyword.else)","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"range":{"startRow":18,"endRow":18,"startColumn":33,"endColumn":53},"id":269,"text":"CodeBlock","type":"other","parent":256,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}]},{"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"leftBrace"},"id":270,"type":"other","structure":[],"parent":269,"range":{"startColumn":33,"endColumn":34,"endRow":18,"startRow":18},"text":"{"},{"range":{"startColumn":35,"endColumn":51,"endRow":18,"startRow":18},"id":271,"text":"CodeBlockItemList","type":"collection","parent":269,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endRow":18,"endColumn":51,"startColumn":35,"startRow":18},"id":272,"text":"CodeBlockItem","type":"other","parent":271,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ThrowStmtSyntax"},"name":"item","ref":"ThrowStmtSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"range":{"endRow":18,"startColumn":35,"endColumn":51,"startRow":18},"id":273,"text":"ThrowStmt","type":"other","parent":272,"structure":[{"name":"unexpectedBeforeThrowKeyword","value":{"text":"nil"}},{"name":"throwKeyword","value":{"text":"throw","kind":"keyword(SwiftSyntax.Keyword.throw)"}},{"name":"unexpectedBetweenThrowKeywordAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.throw)","leadingTrivia":""},"type":"other","text":"throw","parent":273,"range":{"startRow":18,"startColumn":35,"endColumn":40,"endRow":18},"structure":[],"id":274},{"range":{"startRow":18,"startColumn":41,"endColumn":51,"endRow":18},"id":275,"text":"MemberAccessExpr","type":"expr","parent":273,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"nil"},"name":"base"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"kind":"period","text":"."},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"declName"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}]},{"token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"range":{"startColumn":41,"endColumn":42,"endRow":18,"startRow":18},"text":".","type":"other","structure":[],"id":276,"parent":275},{"range":{"startColumn":42,"endColumn":51,"endRow":18,"startRow":18},"id":277,"text":"DeclReferenceExpr","type":"expr","parent":275,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("noRatings")","text":"noRatings"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"range":{"startColumn":42,"endRow":18,"startRow":18,"endColumn":51},"text":"noRatings","token":{"kind":"identifier("noRatings")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"structure":[],"type":"other","parent":277,"id":278},{"structure":[],"text":"}","range":{"startColumn":52,"endRow":18,"startRow":18,"endColumn":53},"id":279,"token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":""},"parent":269,"type":"other"},{"structure":[],"range":{"startColumn":1,"endRow":19,"startRow":19,"endColumn":2},"id":280,"text":"}","type":"other","token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":"↲<\/span>"},"parent":252},{"range":{"startColumn":1,"endRow":21,"startRow":21,"endColumn":38},"id":281,"text":"CodeBlockItem","type":"other","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"range":{"startColumn":1,"endColumn":38,"endRow":21,"startRow":21},"id":282,"text":"VariableDecl","type":"decl","parent":281,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}]},{"range":{"endRow":19,"endColumn":2,"startRow":19,"startColumn":2},"id":283,"text":"AttributeList","type":"collection","parent":282,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"endColumn":6,"endRow":21,"startRow":21,"startColumn":1},"id":284,"text":"DeclModifierList","type":"collection","parent":282,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endRow":21,"startRow":21,"startColumn":1,"endColumn":6},"id":285,"text":"DeclModifier","type":"other","parent":284,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"keyword(SwiftSyntax.Keyword.async)","text":"async"}},{"name":"unexpectedBetweenNameAndDetail","value":{"text":"nil"}},{"name":"detail","value":{"text":"nil"}},{"name":"unexpectedAfterDetail","value":{"text":"nil"}}]},{"range":{"startRow":21,"endColumn":6,"startColumn":1,"endRow":21},"parent":285,"id":286,"type":"other","text":"async","structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.async)","leadingTrivia":"↲<\/span>↲<\/span>"}},{"range":{"startRow":21,"endColumn":10,"startColumn":7,"endRow":21},"parent":282,"text":"let","id":287,"type":"other","structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":""}},{"range":{"startRow":21,"endColumn":38,"startColumn":11,"endRow":21},"id":288,"text":"PatternBindingList","type":"collection","parent":282,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endRow":21,"startColumn":11,"endColumn":38,"startRow":21},"id":289,"text":"PatternBinding","type":"other","parent":288,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax","name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"value":{"text":"nil"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax","name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"startRow":21,"startColumn":11,"endRow":21,"endColumn":15},"id":290,"text":"IdentifierPattern","type":"pattern","parent":289,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("data")","text":"data"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"type":"other","structure":[],"range":{"startRow":21,"endRow":21,"startColumn":11,"endColumn":15},"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"identifier("data")"},"text":"data","id":291,"parent":290},{"range":{"startRow":21,"endRow":21,"startColumn":16,"endColumn":38},"id":292,"text":"InitializerClause","type":"other","parent":289,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"text":"=","kind":"equal"}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"value","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"id":293,"text":"=","range":{"startColumn":16,"endRow":21,"endColumn":17,"startRow":21},"parent":292,"structure":[],"token":{"leadingTrivia":"","kind":"equal","trailingTrivia":"␣<\/span>"},"type":"other"},{"range":{"startColumn":18,"endRow":21,"endColumn":38,"startRow":21},"id":294,"text":"FunctionCallExpr","type":"expr","parent":292,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"range":{"endColumn":31,"startRow":21,"startColumn":18,"endRow":21},"id":295,"text":"DeclReferenceExpr","type":"expr","parent":294,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("fetchUserData")","text":"fetchUserData"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"text":"fetchUserData","range":{"endColumn":31,"endRow":21,"startColumn":18,"startRow":21},"structure":[],"id":296,"type":"other","parent":295,"token":{"trailingTrivia":"","kind":"identifier("fetchUserData")","leadingTrivia":""}},{"type":"other","parent":294,"structure":[],"token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"range":{"endColumn":32,"endRow":21,"startColumn":31,"startRow":21},"id":297,"text":"("},{"range":{"endColumn":37,"endRow":21,"startColumn":32,"startRow":21},"id":298,"text":"LabeledExprList","type":"collection","parent":294,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endColumn":37,"endRow":21,"startRow":21,"startColumn":32},"id":299,"text":"LabeledExpr","type":"other","parent":298,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"id","kind":"identifier("id")"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","value":{"text":"IntegerLiteralExprSyntax"},"ref":"IntegerLiteralExprSyntax"},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"parent":299,"text":"id","type":"other","range":{"startRow":21,"startColumn":32,"endColumn":34,"endRow":21},"token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("id")"},"structure":[],"id":300},{"range":{"startRow":21,"startColumn":34,"endColumn":35,"endRow":21},"structure":[],"type":"other","parent":299,"text":":","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"colon"},"id":301},{"range":{"startRow":21,"startColumn":36,"endColumn":37,"endRow":21},"id":302,"text":"IntegerLiteralExpr","type":"expr","parent":299,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"1","kind":"integerLiteral("1")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"type":"other","token":{"trailingTrivia":"","kind":"integerLiteral("1")","leadingTrivia":""},"id":303,"structure":[],"parent":302,"text":"1","range":{"endRow":21,"startRow":21,"endColumn":37,"startColumn":36}},{"range":{"endRow":21,"startRow":21,"endColumn":38,"startColumn":37},"token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"text":")","type":"other","structure":[],"id":304,"parent":294},{"range":{"endRow":21,"startRow":21,"endColumn":38,"startColumn":38},"id":305,"text":"MultipleTrailingClosureElementList","type":"collection","parent":294,"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"startRow":22,"endRow":22,"endColumn":40,"startColumn":1},"id":306,"text":"CodeBlockItem","type":"other","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"range":{"endRow":22,"endColumn":40,"startColumn":1,"startRow":22},"id":307,"text":"VariableDecl","type":"decl","parent":306,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}]},{"range":{"startRow":21,"startColumn":38,"endRow":21,"endColumn":38},"id":308,"text":"AttributeList","type":"collection","parent":307,"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}]},{"range":{"startColumn":1,"startRow":22,"endRow":22,"endColumn":6},"id":309,"text":"DeclModifierList","type":"collection","parent":307,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"range":{"endColumn":6,"startRow":22,"startColumn":1,"endRow":22},"id":310,"text":"DeclModifier","type":"other","parent":309,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"async","kind":"keyword(SwiftSyntax.Keyword.async)"}},{"name":"unexpectedBetweenNameAndDetail","value":{"text":"nil"}},{"name":"detail","value":{"text":"nil"}},{"name":"unexpectedAfterDetail","value":{"text":"nil"}}]},{"type":"other","range":{"startRow":22,"endColumn":6,"endRow":22,"startColumn":1},"parent":310,"token":{"leadingTrivia":"↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.async)"},"structure":[],"text":"async","id":311},{"text":"let","structure":[],"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)"},"type":"other","id":312,"parent":307,"range":{"startRow":22,"endColumn":10,"endRow":22,"startColumn":7}},{"range":{"startRow":22,"endColumn":40,"endRow":22,"startColumn":11},"id":313,"text":"PatternBindingList","type":"collection","parent":307,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endColumn":40,"startRow":22,"startColumn":11,"endRow":22},"id":314,"text":"PatternBinding","type":"other","parent":313,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","value":{"text":"IdentifierPatternSyntax"},"ref":"IdentifierPatternSyntax"},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"InitializerClauseSyntax"},"ref":"InitializerClauseSyntax"},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startRow":22,"startColumn":11,"endRow":22,"endColumn":16},"id":315,"text":"IdentifierPattern","type":"pattern","parent":314,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"posts","kind":"identifier("posts")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"text":"posts","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"identifier("posts")"},"parent":315,"range":{"endRow":22,"startRow":22,"startColumn":11,"endColumn":16},"type":"other","id":316,"structure":[]},{"range":{"endRow":22,"startRow":22,"startColumn":17,"endColumn":40},"id":317,"text":"InitializerClause","type":"other","parent":314,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"name":"value","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"parent":317,"structure":[],"token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"id":318,"type":"other","text":"=","range":{"endColumn":18,"startRow":22,"startColumn":17,"endRow":22}},{"range":{"endColumn":40,"startRow":22,"startColumn":19,"endRow":22},"id":319,"text":"FunctionCallExpr","type":"expr","parent":317,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}]},{"range":{"startRow":22,"endRow":22,"startColumn":19,"endColumn":33},"id":320,"text":"DeclReferenceExpr","type":"expr","parent":319,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"fetchUserPosts","kind":"identifier("fetchUserPosts")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"structure":[],"text":"fetchUserPosts","range":{"endRow":22,"endColumn":33,"startRow":22,"startColumn":19},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("fetchUserPosts")"},"type":"other","id":321,"parent":320},{"structure":[],"parent":319,"text":"(","range":{"endRow":22,"endColumn":34,"startRow":22,"startColumn":33},"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"id":322,"type":"other"},{"range":{"endRow":22,"endColumn":39,"startRow":22,"startColumn":34},"id":323,"text":"LabeledExprList","type":"collection","parent":319,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"startRow":22,"startColumn":34,"endColumn":39,"endRow":22},"id":324,"text":"LabeledExpr","type":"other","parent":323,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"kind":"identifier("id")","text":"id"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"kind":"colon","text":":"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"IntegerLiteralExprSyntax"},"name":"expression","ref":"IntegerLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}]},{"range":{"startColumn":34,"startRow":22,"endRow":22,"endColumn":36},"id":325,"token":{"kind":"identifier("id")","leadingTrivia":"","trailingTrivia":""},"type":"other","text":"id","parent":324,"structure":[]},{"range":{"startColumn":36,"startRow":22,"endRow":22,"endColumn":37},"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":324,"id":326,"text":":","type":"other","structure":[]},{"range":{"startColumn":38,"startRow":22,"endRow":22,"endColumn":39},"id":327,"text":"IntegerLiteralExpr","type":"expr","parent":324,"structure":[{"name":"unexpectedBeforeLiteral","value":{"text":"nil"}},{"name":"literal","value":{"text":"1","kind":"integerLiteral("1")"}},{"name":"unexpectedAfterLiteral","value":{"text":"nil"}}]},{"text":"1","id":328,"token":{"leadingTrivia":"","kind":"integerLiteral("1")","trailingTrivia":""},"range":{"startColumn":38,"startRow":22,"endColumn":39,"endRow":22},"type":"other","parent":327,"structure":[]},{"parent":319,"type":"other","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"text":")","id":329,"structure":[],"range":{"startColumn":39,"startRow":22,"endColumn":40,"endRow":22}},{"range":{"startColumn":40,"startRow":22,"endColumn":40,"endRow":22},"id":330,"text":"MultipleTrailingClosureElementList","type":"collection","parent":319,"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"endRow":23,"endColumn":58,"startColumn":1,"startRow":23},"id":331,"text":"CodeBlockItem","type":"other","parent":1,"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}]},{"range":{"startColumn":1,"endColumn":58,"startRow":23,"endRow":23},"id":332,"text":"VariableDecl","type":"decl","parent":331,"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}]},{"range":{"startRow":22,"endRow":22,"endColumn":40,"startColumn":40},"id":333,"text":"AttributeList","type":"collection","parent":332,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}]},{"range":{"startColumn":40,"startRow":22,"endRow":22,"endColumn":40},"id":334,"text":"DeclModifierList","type":"collection","parent":332,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"0"}}]},{"parent":332,"structure":[],"range":{"startColumn":1,"endRow":23,"startRow":23,"endColumn":4},"text":"let","id":335,"token":{"trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.let)","leadingTrivia":"↲<\/span>"},"type":"other"},{"range":{"startColumn":5,"endRow":23,"startRow":23,"endColumn":58},"id":336,"text":"PatternBindingList","type":"collection","parent":332,"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"range":{"endColumn":58,"startRow":23,"startColumn":5,"endRow":23},"id":337,"text":"PatternBinding","type":"other","parent":336,"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"ref":"TuplePatternSyntax","name":"pattern","value":{"text":"TuplePatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","value":{"text":"nil"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"ref":"InitializerClauseSyntax","name":"initializer","value":{"text":"InitializerClauseSyntax"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"endRow":23,"startRow":23,"startColumn":5,"endColumn":32},"id":338,"text":"TuplePattern","type":"pattern","parent":337,"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndElements","value":{"text":"nil"}},{"name":"elements","value":{"text":"TuplePatternElementListSyntax"},"ref":"TuplePatternElementListSyntax"},{"name":"unexpectedBetweenElementsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}]},{"parent":338,"type":"other","text":"(","token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":23,"startColumn":5,"endRow":23,"endColumn":6},"structure":[],"id":339},{"range":{"startRow":23,"startColumn":6,"endRow":23,"endColumn":31},"id":340,"text":"TuplePatternElementList","type":"collection","parent":338,"structure":[{"value":{"text":"TuplePatternElementSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}]},{"range":{"endRow":23,"startColumn":6,"endColumn":18,"startRow":23},"id":341,"text":"TuplePatternElement","type":"other","parent":340,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndPattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"endColumn":17,"startRow":23,"endRow":23,"startColumn":6},"id":342,"text":"IdentifierPattern","type":"pattern","parent":341,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeIdentifier"},{"value":{"text":"fetchedData","kind":"identifier("fetchedData")"},"name":"identifier"},{"value":{"text":"nil"},"name":"unexpectedAfterIdentifier"}]},{"range":{"startColumn":6,"startRow":23,"endColumn":17,"endRow":23},"parent":342,"id":343,"structure":[],"text":"fetchedData","type":"other","token":{"kind":"identifier("fetchedData")","leadingTrivia":"","trailingTrivia":""}},{"range":{"startColumn":17,"startRow":23,"endColumn":18,"endRow":23},"parent":341,"type":"other","text":",","structure":[],"token":{"kind":"comma","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"id":344},{"range":{"startColumn":19,"startRow":23,"endColumn":31,"endRow":23},"id":345,"text":"TuplePatternElement","type":"other","parent":340,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndPattern","value":{"text":"nil"}},{"ref":"IdentifierPatternSyntax","name":"pattern","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startRow":23,"endColumn":31,"startColumn":19,"endRow":23},"id":346,"text":"IdentifierPattern","type":"pattern","parent":345,"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"fetchedPosts","kind":"identifier("fetchedPosts")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}]},{"text":"fetchedPosts","id":347,"type":"other","range":{"endColumn":31,"startRow":23,"endRow":23,"startColumn":19},"structure":[],"token":{"trailingTrivia":"","kind":"identifier("fetchedPosts")","leadingTrivia":""},"parent":346},{"token":{"trailingTrivia":"␣<\/span>","kind":"rightParen","leadingTrivia":""},"structure":[],"type":"other","text":")","id":348,"parent":338,"range":{"endColumn":32,"startRow":23,"endRow":23,"startColumn":31}},{"range":{"endColumn":58,"startRow":23,"endRow":23,"startColumn":33},"id":349,"text":"InitializerClause","type":"other","parent":337,"structure":[{"name":"unexpectedBeforeEqual","value":{"text":"nil"}},{"name":"equal","value":{"kind":"equal","text":"="}},{"name":"unexpectedBetweenEqualAndValue","value":{"text":"nil"}},{"ref":"TryExprSyntax","name":"value","value":{"text":"TryExprSyntax"}},{"name":"unexpectedAfterValue","value":{"text":"nil"}}]},{"id":350,"text":"=","token":{"trailingTrivia":"␣<\/span>","kind":"equal","leadingTrivia":""},"structure":[],"range":{"startColumn":33,"startRow":23,"endRow":23,"endColumn":34},"type":"other","parent":349},{"range":{"startColumn":35,"startRow":23,"endRow":23,"endColumn":58},"id":351,"text":"TryExpr","type":"expr","parent":349,"structure":[{"name":"unexpectedBeforeTryKeyword","value":{"text":"nil"}},{"name":"tryKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.try)","text":"try"}},{"name":"unexpectedBetweenTryKeywordAndQuestionOrExclamationMark","value":{"text":"nil"}},{"name":"questionOrExclamationMark","value":{"text":"nil"}},{"name":"unexpectedBetweenQuestionOrExclamationMarkAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"AwaitExprSyntax","value":{"text":"AwaitExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"type":"other","id":352,"token":{"kind":"keyword(SwiftSyntax.Keyword.try)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endColumn":38,"startColumn":35,"endRow":23,"startRow":23},"parent":351,"text":"try","structure":[]},{"range":{"endColumn":58,"startColumn":39,"endRow":23,"startRow":23},"id":353,"text":"AwaitExpr","type":"expr","parent":351,"structure":[{"name":"unexpectedBeforeAwaitKeyword","value":{"text":"nil"}},{"name":"awaitKeyword","value":{"text":"await","kind":"keyword(SwiftSyntax.Keyword.await)"}},{"name":"unexpectedBetweenAwaitKeywordAndExpression","value":{"text":"nil"}},{"ref":"TupleExprSyntax","name":"expression","value":{"text":"TupleExprSyntax"}},{"name":"unexpectedAfterExpression","value":{"text":"nil"}}]},{"structure":[],"id":354,"text":"await","token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.await)"},"parent":353,"range":{"startColumn":39,"endColumn":44,"startRow":23,"endRow":23},"type":"other"},{"range":{"startColumn":45,"endColumn":58,"startRow":23,"endRow":23},"id":355,"text":"TupleExpr","type":"expr","parent":353,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndElements"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"elements"},{"value":{"text":"nil"},"name":"unexpectedBetweenElementsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}]},{"parent":355,"range":{"endRow":23,"startColumn":45,"endColumn":46,"startRow":23},"type":"other","structure":[],"token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftParen"},"id":356,"text":"("},{"range":{"endRow":23,"startColumn":46,"endColumn":57,"startRow":23},"id":357,"text":"LabeledExprList","type":"collection","parent":355,"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}]},{"range":{"endRow":23,"startRow":23,"endColumn":51,"startColumn":46},"id":358,"text":"LabeledExpr","type":"other","parent":357,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":",","kind":"comma"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startColumn":46,"endRow":23,"startRow":23,"endColumn":50},"id":359,"text":"DeclReferenceExpr","type":"expr","parent":358,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("data")","text":"data"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}]},{"type":"other","text":"data","token":{"leadingTrivia":"","kind":"identifier("data")","trailingTrivia":""},"structure":[],"range":{"startColumn":46,"startRow":23,"endRow":23,"endColumn":50},"parent":359,"id":360},{"token":{"leadingTrivia":"","kind":"comma","trailingTrivia":"␣<\/span>"},"id":361,"text":",","type":"other","structure":[],"parent":358,"range":{"startColumn":50,"startRow":23,"endRow":23,"endColumn":51}},{"range":{"startColumn":52,"startRow":23,"endRow":23,"endColumn":57},"id":362,"text":"LabeledExpr","type":"other","parent":357,"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}]},{"range":{"startColumn":52,"endRow":23,"endColumn":57,"startRow":23},"id":363,"text":"DeclReferenceExpr","type":"expr","parent":362,"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("posts")","text":"posts"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}]},{"structure":[],"token":{"leadingTrivia":"","kind":"identifier("posts")","trailingTrivia":""},"id":364,"range":{"endColumn":57,"endRow":23,"startRow":23,"startColumn":52},"text":"posts","type":"other","parent":363},{"range":{"endColumn":58,"endRow":23,"startRow":23,"startColumn":57},"type":"other","parent":355,"id":365,"structure":[],"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"text":")"},{"token":{"leadingTrivia":"","kind":"endOfFile","trailingTrivia":""},"text":"","id":366,"type":"other","parent":0,"range":{"endColumn":58,"endRow":23,"startRow":23,"startColumn":58},"structure":[]}] diff --git a/Examples/Remaining/concurrency/code.swift b/Examples/Remaining/concurrency/code.swift deleted file mode 100644 index 21be8c3..0000000 --- a/Examples/Remaining/concurrency/code.swift +++ /dev/null @@ -1,87 +0,0 @@ -import Foundation - -// MARK: - Async Functions -func fetchUserData(id: Int) async throws -> String { - // Simulate network delay - try await Task.sleep(nanoseconds: 1_000_000_000) // 1 second - return "User data for ID: \(id)" -} - -func fetchUserPosts(id: Int) async throws -> [String] { - // Simulate network delay - try await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds - return ["Post 1", "Post 2", "Post 3"] -} - -// MARK: - Async Sequence -struct Countdown: AsyncSequence { - let start: Int - - struct AsyncIterator: AsyncIteratorProtocol { - var count: Int - - mutating func next() async -> Int? { - guard !isEmpty else { return nil } - try? await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds - let current = count - count -= 1 - return current - } - } - - func makeAsyncIterator() -> AsyncIterator { - AsyncIterator(count: start) - } -} - -// MARK: - Task Groups -func fetchMultipleUsers(ids: [Int]) async throws -> [String] { - try await withThrowingTaskGroup(of: String.self) { group in - for id in ids { - group.addTask { - try await fetchUserData(id: id) - } - } - - var results: [String] = [] - for try await result in group { - results.append(result) - } - return results - } -} - -// MARK: - Usage Example -@main -struct ConcurrencyExample { - static func main() async { - do { - // Demonstrate basic async/await - print("Fetching user data...") - let userData = try await fetchUserData(id: 1) - print(userData) - - // Demonstrate concurrent tasks - print("\nFetching user data and posts concurrently...") - async let data = fetchUserData(id: 1) - async let posts = fetchUserPosts(id: 1) - let (fetchedData, fetchedPosts) = try await (data, posts) - print("Data: \(fetchedData)") - print("Posts: \(fetchedPosts)") - - // Demonstrate async sequence - print("\nStarting countdown:") - for await number in Countdown(start: 3) { - print(number) - } - print("Liftoff!") - - // Demonstrate task groups - print("\nFetching multiple users:") - let users = try await fetchMultipleUsers(ids: [1, 2, 3]) - print(users) - } catch { - print("Error: \(error)") - } - } -} diff --git a/Examples/Remaining/result_builders/code.swift b/Examples/Remaining/result_builders/code.swift new file mode 100644 index 0000000..148b74e --- /dev/null +++ b/Examples/Remaining/result_builders/code.swift @@ -0,0 +1,58 @@ + +var vendingMachine = VendingMachine() +vendingMachine.coinsDeposited = 8 +do { + try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) + print("Success! Yum.") +} catch VendingMachineError.invalidSelection { + print("Invalid Selection.") +} catch VendingMachineError.outOfStock { + print("Out of Stock.") +} catch VendingMachineError.insufficientFunds(let coinsNeeded) { + print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.") +} catch { + print("Unexpected error: \(error).") +} + +func summarize(_ ratings: [Int]) throws(StatisticsError) { + guard !ratings.isEmpty else { throw .noRatings } +} + +// MARK: - Task Groups +func fetchMultipleUsers(ids: [Int]) async throws -> [String] { + try await withThrowingTaskGroup(of: String.self) { group in + for id in ids { + group.addTask { + try await fetchUserData(id: id) + } + } + + var results: [String] = [] + for try await result in group { + results.append(result) + } + return results + } +} + +// Demonstrate concurrent tasks +print("\nFetching user data and posts concurrently...") +async let data = fetchUserData(id: 1) +async let posts = fetchUserPosts(id: 1) +let (fetchedData, fetchedPosts) = try await (data, posts) +print("Data: \(fetchedData)") +print("Posts: \(fetchedPosts)") + + +Task { + _ = try await fetchUserData(id: 1) +} + +Task { @MainActor [unowned self] in + _ = try await fetchUserData(id: 1) +} + + +func nonThrowingFunction() throws(Never) { + +} \ No newline at end of file diff --git a/Line.swift b/Line.swift index 29be4c6..41374c1 100644 --- a/Line.swift +++ b/Line.swift @@ -5,7 +5,8 @@ // Created by Leo Dion on 6/16/25. // -/// Represents a single comment line that can be attached to a syntax node when using `.comment { ... }` in the DSL. +/// Represents a single comment line that can be attached to a syntax node when using +/// `.comment { ... }` in the DSL. public struct Line { public enum Kind { /// Regular line comment that starts with `//`. diff --git a/Sources/SyntaxKit/Assignment.swift b/Sources/SyntaxKit/Assignment.swift index a6502da..b3e26ac 100644 --- a/Sources/SyntaxKit/Assignment.swift +++ b/Sources/SyntaxKit/Assignment.swift @@ -71,7 +71,8 @@ public struct Assignment: CodeBlock { elements: ExprListSyntax([ left, ExprSyntax( - AssignmentExprSyntax(equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space))), + AssignmentExprSyntax(equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space)) + ), right, ]) ) diff --git a/Sources/SyntaxKit/Call.swift b/Sources/SyntaxKit/Call.swift index 05bdc09..f3df787 100644 --- a/Sources/SyntaxKit/Call.swift +++ b/Sources/SyntaxKit/Call.swift @@ -33,6 +33,8 @@ import SwiftSyntax public struct Call: CodeBlock { private let functionName: String private let parameters: [ParameterExp] + private var isThrowing: Bool = false + private var isAsync: Bool = false /// Creates a global function call expression. /// - Parameter functionName: The name of the function to call. @@ -50,6 +52,22 @@ public struct Call: CodeBlock { self.parameters = params() } + /// Marks this function call as throwing. + /// - Returns: A copy of the call marked as throwing. + public func throwing() -> Self { + var copy = self + copy.isThrowing = true + return copy + } + + /// Marks this function call as async. + /// - Returns: A copy of the call marked as async. + public func async() -> Self { + var copy = self + copy.isAsync = true + return copy + } + public var syntax: SyntaxProtocol { let function = TokenSyntax.identifier(functionName) let args = LabeledExprListSyntax( @@ -73,12 +91,29 @@ public struct Call: CodeBlock { } }) - return ExprSyntax( - FunctionCallExprSyntax( - calledExpression: ExprSyntax(DeclReferenceExprSyntax(baseName: function)), - leftParen: .leftParenToken(), - arguments: args, - rightParen: .rightParenToken() - )) + let functionCall = FunctionCallExprSyntax( + calledExpression: ExprSyntax(DeclReferenceExprSyntax(baseName: function)), + leftParen: .leftParenToken(), + arguments: args, + rightParen: .rightParenToken() + ) + + if isThrowing { + return ExprSyntax( + TryExprSyntax( + tryKeyword: .keyword(.try, trailingTrivia: .space), + expression: functionCall + ) + ) + } else if isAsync { + return ExprSyntax( + AwaitExprSyntax( + awaitKeyword: .keyword(.await, trailingTrivia: .space), + expression: functionCall + ) + ) + } else { + return ExprSyntax(functionCall) + } } } diff --git a/Sources/SyntaxKit/Case.swift b/Sources/SyntaxKit/Case.swift index 18c8e59..14951df 100644 --- a/Sources/SyntaxKit/Case.swift +++ b/Sources/SyntaxKit/Case.swift @@ -29,10 +29,13 @@ import SwiftSyntax -/// A `case` in a `switch` statement with tuple-style patterns. +/// A `case` in a `switch` statement with tuple-style patterns, or an enum case declaration. public struct Case: CodeBlock { private let patterns: [PatternConvertible] private let body: [CodeBlock] + private let isEnumCase: Bool + private let enumCaseName: String? + private var associatedValue: (name: String, type: String)? /// Creates a `case` for a `switch` statement. /// - Parameters: @@ -42,6 +45,30 @@ public struct Case: CodeBlock { { self.patterns = patterns self.body = content() + self.isEnumCase = false + self.enumCaseName = nil + self.associatedValue = nil + } + + /// Creates an enum case declaration. + /// - Parameter name: The name of the enum case. + public init(_ name: String) { + self.patterns = [] + self.body = [] + self.isEnumCase = true + self.enumCaseName = name + self.associatedValue = nil + } + + /// Sets the associated value for the enum case. + /// - Parameters: + /// - name: The name of the associated value. + /// - type: The type of the associated value. + /// - Returns: A copy of the case with the associated value set. + public func associatedValue(_ name: String, type: String) -> Self { + var copy = self + copy.associatedValue = (name: name, type: type) + return copy } public var switchCaseSyntax: SwitchCaseSyntax { @@ -77,5 +104,47 @@ public struct Case: CodeBlock { ) } - public var syntax: SyntaxProtocol { switchCaseSyntax } + public var syntax: SyntaxProtocol { + if isEnumCase { + // Handle enum case declaration + let caseKeyword = TokenSyntax.keyword(.case, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(enumCaseName ?? "", trailingTrivia: .space) + + var parameterClause: EnumCaseParameterClauseSyntax? + if let associated = associatedValue { + let parameter = EnumCaseParameterSyntax( + firstName: nil, + secondName: .identifier(associated.name), + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + type: TypeSyntax(IdentifierTypeSyntax(name: .identifier(associated.type))) + ) + parameterClause = EnumCaseParameterClauseSyntax( + leftParen: .leftParenToken(), + parameters: EnumCaseParameterListSyntax([parameter]), + rightParen: .rightParenToken() + ) + } + + return EnumCaseDeclSyntax( + caseKeyword: caseKeyword, + elements: EnumCaseElementListSyntax([ + EnumCaseElementSyntax( + leadingTrivia: .space, + _: nil, + name: associatedValue != nil ? TokenSyntax.identifier(enumCaseName ?? "") : identifier, + _: nil, + parameterClause: parameterClause, + _: nil, + rawValue: nil, + _: nil, + trailingComma: nil, + trailingTrivia: .newline + ) + ]) + ) + } else { + // Handle switch case + return switchCaseSyntax + } + } } diff --git a/Sources/SyntaxKit/Catch.swift b/Sources/SyntaxKit/Catch.swift new file mode 100644 index 0000000..a4db19a --- /dev/null +++ b/Sources/SyntaxKit/Catch.swift @@ -0,0 +1,198 @@ +// +// Catch.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// A Swift `catch` clause for error handling. +public struct Catch: CodeBlock { + private let pattern: CodeBlock? + private let body: [CodeBlock] + + /// Creates a `catch` clause with a pattern. + /// - Parameters: + /// - pattern: The pattern to match for this catch clause. + /// - content: A ``CodeBlockBuilder`` that provides the body of the catch clause. + public init( + _ pattern: CodeBlock, + @CodeBlockBuilderResult _ content: () -> [CodeBlock] + ) { + self.pattern = pattern + self.body = content() + } + + /// Creates a `catch` clause without a pattern (catches all errors). + /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the catch clause. + public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.pattern = nil + self.body = content() + } + + /// Creates a `catch` clause for a specific enum case. + /// - Parameters: + /// - enumCase: The enum case to catch. + /// - content: A ``CodeBlockBuilder`` that provides the body of the catch clause. + public static func `catch`( + _ enumCase: EnumCase, + @CodeBlockBuilderResult _ content: () -> [CodeBlock] + ) -> Catch { + Catch(enumCase, content) + } + + public var catchClauseSyntax: CatchClauseSyntax { + // Build catch items (patterns) + var catchItems: CatchItemListSyntax? + if let pattern = pattern { + var patternSyntax: PatternSyntax + + if let enumCase = pattern as? EnumCase { + if !enumCase.caseAssociatedValues.isEmpty { + let baseName = enumCase.caseName + let baseParts = baseName.split(separator: ".") + let (typeName, caseName) = + baseParts.count == 2 ? (String(baseParts[0]), String(baseParts[1])) : ("", baseName) + // Build the pattern: .caseName(let a, let b) + let memberAccess = MemberAccessExprSyntax( + base: typeName.isEmpty + ? nil : ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(typeName))), + dot: .periodToken(), + name: .identifier(caseName) + ) + let patternWithTuple = PatternSyntax( + ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.case, trailingTrivia: .space), + pattern: PatternSyntax( + ExpressionPatternSyntax( + expression: ExprSyntax(memberAccess) + ) + ) + ) + ) + // Actually, Swift's catch pattern for associated values is: .caseName(let a, let b) + // So we want: ExpressionPatternSyntax(MemberAccessExprSyntax + tuplePattern) + let tuplePattern = TuplePatternSyntax( + leftParen: .leftParenToken(), + elements: TuplePatternElementListSyntax( + enumCase.caseAssociatedValues.enumerated().map { index, associated in + TuplePatternElementSyntax( + pattern: PatternSyntax( + ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: PatternSyntax( + IdentifierPatternSyntax(identifier: .identifier(associated.name)) + ) + ) + ), + trailingComma: index < enumCase.caseAssociatedValues.count - 1 + ? .commaToken(trailingTrivia: .space) : nil + ) + } + ), + rightParen: .rightParenToken() + ) + let patternSyntaxExpr = ExprSyntax( + FunctionCallExprSyntax( + calledExpression: ExprSyntax(memberAccess), + leftParen: .leftParenToken(), + arguments: LabeledExprListSyntax( + enumCase.caseAssociatedValues.enumerated().map { index, associated in + LabeledExprSyntax( + label: nil, + colon: nil, + expression: ExprSyntax( + PatternExprSyntax( + pattern: PatternSyntax( + ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: PatternSyntax( + IdentifierPatternSyntax(identifier: .identifier(associated.name)) + ) + ) + ) + ) + ), + trailingComma: index < enumCase.caseAssociatedValues.count - 1 + ? .commaToken(trailingTrivia: .space) : nil + ) + } + ), + rightParen: .rightParenToken() + ) + ) + patternSyntax = PatternSyntax(ExpressionPatternSyntax(expression: patternSyntaxExpr)) + } else { + let enumCaseExpr = enumCase.asExpressionSyntax + patternSyntax = PatternSyntax(ExpressionPatternSyntax(expression: enumCaseExpr)) + } + } else { + // Handle other patterns + patternSyntax = PatternSyntax( + ExpressionPatternSyntax( + expression: ExprSyntax( + fromProtocol: pattern.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + ) + ) + } + + catchItems = CatchItemListSyntax([ + CatchItemSyntax(pattern: patternSyntax) + ]) + } + + // Build catch body + let catchBody = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax( + body.compactMap { + var item: CodeBlockItemSyntax? + if let decl = $0.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = $0.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = $0.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + }), + rightBrace: .rightBraceToken(leadingTrivia: .newline, trailingTrivia: .space) + ) + + return CatchClauseSyntax( + catchKeyword: .keyword(.catch, trailingTrivia: .space), + catchItems: catchItems ?? CatchItemListSyntax([]), + body: catchBody + ) + } + + public var syntax: SyntaxProtocol { + catchClauseSyntax + } +} diff --git a/Sources/SyntaxKit/CatchBuilder.swift b/Sources/SyntaxKit/CatchBuilder.swift new file mode 100644 index 0000000..6991d2a --- /dev/null +++ b/Sources/SyntaxKit/CatchBuilder.swift @@ -0,0 +1,62 @@ +// +// CatchBuilder.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A result builder for creating catch clauses in a do-catch statement. +@resultBuilder +public struct CatchBuilder { + public static func buildBlock(_ components: CatchClauseSyntax...) -> CatchClauseListSyntax { + CatchClauseListSyntax(components) + } + + public static func buildExpression(_ expression: CatchClauseSyntax) -> CatchClauseSyntax { + expression + } + + public static func buildExpression(_ expression: Catch) -> CatchClauseSyntax { + expression.catchClauseSyntax + } + + public static func buildOptional(_ component: CatchClauseSyntax?) -> CatchClauseSyntax? { + component + } + + public static func buildEither(first component: CatchClauseSyntax) -> CatchClauseSyntax { + component + } + + public static func buildEither(second component: CatchClauseSyntax) -> CatchClauseSyntax { + component + } + + public static func buildArray(_ components: [CatchClauseSyntax]) -> CatchClauseListSyntax { + CatchClauseListSyntax(components) + } +} diff --git a/Sources/SyntaxKit/CodeBlock+Generate.swift b/Sources/SyntaxKit/CodeBlock+Generate.swift index 9acbb9e..ecde6e4 100644 --- a/Sources/SyntaxKit/CodeBlock+Generate.swift +++ b/Sources/SyntaxKit/CodeBlock+Generate.swift @@ -37,6 +37,9 @@ extension CodeBlock { let statements: CodeBlockItemListSyntax if let list = self.syntax.as(CodeBlockItemListSyntax.self) { statements = list + } else if let codeBlock = self.syntax.as(CodeBlockSyntax.self) { + // Handle CodeBlockSyntax by extracting its statements + statements = codeBlock.statements } else { let item: CodeBlockItemSyntax.Item if let decl = self.syntax.as(DeclSyntax.self) { @@ -62,7 +65,8 @@ extension CodeBlock { item = .expr(ExprSyntax(switchExpr)) } else { fatalError( - "Unsupported syntax type at top level: \(type(of: self.syntax)) generating from \(self)") + "Unsupported syntax type at top level: \(type(of: self.syntax)) (\(self.syntax)) generating from \(self)" + ) } statements = CodeBlockItemListSyntax([ CodeBlockItemSyntax(item: item, trailingTrivia: .newline) diff --git a/Sources/SyntaxKit/Default.swift b/Sources/SyntaxKit/Default.swift index ff38a43..9ccb5b3 100644 --- a/Sources/SyntaxKit/Default.swift +++ b/Sources/SyntaxKit/Default.swift @@ -50,7 +50,8 @@ public struct Default: CodeBlock { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - }) + } + ) let label = SwitchDefaultLabelSyntax( defaultKeyword: .keyword(.default), colon: .colonToken(trailingTrivia: .newline) diff --git a/Sources/SyntaxKit/DictionaryExpr.swift b/Sources/SyntaxKit/DictionaryExpr.swift new file mode 100644 index 0000000..5ff079c --- /dev/null +++ b/Sources/SyntaxKit/DictionaryExpr.swift @@ -0,0 +1,89 @@ +// +// DictionaryExpr.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A dictionary expression that can contain both Literal types and CodeBlock types. +public struct DictionaryExpr: CodeBlock, LiteralValue { + private let elements: [(DictionaryValue, DictionaryValue)] + + /// Creates a dictionary expression with the given key-value pairs. + /// - Parameter elements: The dictionary key-value pairs. + public init(_ elements: [(DictionaryValue, DictionaryValue)]) { + self.elements = elements + } + + /// The Swift type name for this dictionary. + public var typeName: String { + if elements.isEmpty { + return "[Any: Any]" + } + return "[String: Any]" + } + + /// Renders this dictionary as a Swift literal string. + public var literalString: String { + let elementStrings = elements.map { _, _ in + let keyString: String + let valueString: String + + // For now, we'll use a simple representation + // In a real implementation, we'd need to convert DictionaryValue to string + keyString = "key" + valueString = "value" + + return "\(keyString): \(valueString)" + } + return "[\(elementStrings.joined(separator: ", "))]" + } + + public var syntax: SyntaxProtocol { + if elements.isEmpty { + // Empty dictionary should generate [:] + return DictionaryExprSyntax( + leftSquare: .leftSquareToken(), + content: .colon(.colonToken(leadingTrivia: .init(), trailingTrivia: .init())), + rightSquare: .rightSquareToken() + ) + } else { + let dictionaryElements = DictionaryElementListSyntax( + elements.enumerated().map { index, keyValue in + let (key, value) = keyValue + return DictionaryElementSyntax( + keyExpression: key.exprSyntax, + colon: .colonToken(), + valueExpression: value.exprSyntax, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return DictionaryExprSyntax(content: .elements(dictionaryElements)) + } + } +} diff --git a/Sources/SyntaxKit/DictionaryLiteral.swift b/Sources/SyntaxKit/DictionaryLiteral.swift index 17200ef..c2d7de7 100644 --- a/Sources/SyntaxKit/DictionaryLiteral.swift +++ b/Sources/SyntaxKit/DictionaryLiteral.swift @@ -29,7 +29,7 @@ import Foundation -/// A dictionary value that can be used as a literal. +/// A dictionary literal value that can be used as a literal. public struct DictionaryLiteral: LiteralValue { let elements: [(Literal, Literal)] diff --git a/Sources/SyntaxKit/DictionaryValue.swift b/Sources/SyntaxKit/DictionaryValue.swift new file mode 100644 index 0000000..b8bb8e2 --- /dev/null +++ b/Sources/SyntaxKit/DictionaryValue.swift @@ -0,0 +1,72 @@ +// +// DictionaryValue.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A protocol for types that can be used as dictionary keys or values. +/// This includes both Literal types and CodeBlock types that can be converted to expressions. +public protocol DictionaryValue { + /// The expression syntax representation of this dictionary value. + var exprSyntax: ExprSyntax { get } +} + +// MARK: - Literal Conformance + +extension Literal: DictionaryValue { + // Literal already has exprSyntax from ExprCodeBlock protocol +} + +// MARK: - CodeBlock Conformance + +extension CodeBlock where Self: DictionaryValue { + /// Converts this code block to an expression syntax. + /// If the code block is already an expression, returns it directly. + /// If it's a token, wraps it in a declaration reference expression. + /// Otherwise, throws a fatal error. + public var exprSyntax: ExprSyntax { + if let expr = self.syntax.as(ExprSyntax.self) { + return expr + } + + if let token = self.syntax.as(TokenSyntax.self) { + return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) + } + + fatalError("CodeBlock of type \(type(of: self.syntax)) cannot be represented as ExprSyntax") + } +} + +// MARK: - Specific CodeBlock Types + +extension Call: DictionaryValue {} +extension Init: DictionaryValue {} +extension VariableExp: DictionaryValue {} +extension PropertyAccessExp: DictionaryValue {} +extension FunctionCallExp: DictionaryValue {} +extension Infix: DictionaryValue {} diff --git a/Sources/SyntaxKit/Do.swift b/Sources/SyntaxKit/Do.swift new file mode 100644 index 0000000..d9279db --- /dev/null +++ b/Sources/SyntaxKit/Do.swift @@ -0,0 +1,78 @@ +// +// Do.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// A Swift `do` statement for error handling. +public struct Do: CodeBlock { + private let body: [CodeBlock] + private let catchClauses: CatchClauseListSyntax + + /// Creates a `do-catch` statement. + /// - Parameters: + /// - body: A ``CodeBlockBuilder`` that provides the body of the do block. + /// - catchClauses: A ``CatchBuilder`` that provides the catch clauses. + public init( + @CodeBlockBuilderResult _ body: () -> [CodeBlock], + @CatchBuilder catch catchClauses: () -> CatchClauseListSyntax + ) { + self.body = body() + self.catchClauses = catchClauses() + } + + public var syntax: SyntaxProtocol { + // Build the do body + let doBody = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax( + body.compactMap { + var item: CodeBlockItemSyntax? + if let decl = $0.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = $0.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = $0.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + } + ), + rightBrace: .rightBraceToken(leadingTrivia: .newline, trailingTrivia: .space) + ) + + return StmtSyntax( + DoStmtSyntax( + doKeyword: .keyword(.do, trailingTrivia: .space), + body: doBody, + catchClauses: catchClauses + ) + ) + } +} diff --git a/Sources/SyntaxKit/EnumCase+Syntax.swift b/Sources/SyntaxKit/EnumCase+Syntax.swift new file mode 100644 index 0000000..d122bf8 --- /dev/null +++ b/Sources/SyntaxKit/EnumCase+Syntax.swift @@ -0,0 +1,133 @@ +// +// EnumCase+Syntax.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension EnumCase { + /// Returns the appropriate syntax based on context. + /// When used in expressions (throw, return, if bodies), returns expression syntax. + /// When used in declarations (enum cases), returns declaration syntax. + public var syntax: SyntaxProtocol { + // Check if we're in an expression context by looking at the call stack + // For now, we'll use a heuristic: if this is being used in a context that expects expressions, + // we'll return the expression syntax. Otherwise, we'll return the declaration syntax. + + // Since we can't easily determine context from here, we'll provide both options + // and let the calling code choose. For now, we'll default to declaration syntax + // and let specific contexts (like Throw) handle the conversion. + + let caseKeyword = TokenSyntax.keyword(.case, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) + + var parameterClause: EnumCaseParameterClauseSyntax? + if !associatedValues.isEmpty { + let parameters = EnumCaseParameterListSyntax( + associatedValues.map { associated in + EnumCaseParameterSyntax( + firstName: .identifier(associated.name), + secondName: .identifier(associated.name), + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + type: TypeSyntax(IdentifierTypeSyntax(name: .identifier(associated.type))) + ) + } + ) + parameterClause = EnumCaseParameterClauseSyntax( + leftParen: .leftParenToken(), + parameters: parameters, + rightParen: .rightParenToken() + ) + } + + var initializer: InitializerClauseSyntax? + if let literal = literalValue { + switch literal { + case .string(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: StringLiteralExprSyntax( + openingQuote: .stringQuoteToken(), + segments: StringLiteralSegmentListSyntax([ + .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) + ]), + closingQuote: .stringQuoteToken() + ) + ) + case .float(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: FloatLiteralExprSyntax(literal: .floatLiteral(String(value))) + ) + case .integer(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(value))) + ) + case .nil: + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) + ) + case .boolean(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) + ) + case .ref(let value): + initializer = InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: DeclReferenceExprSyntax(baseName: .identifier(value)) + ) + case .tuple: + fatalError("Tuple is not supported as a raw value for enum cases.") + case .array: + fatalError("Array is not supported as a raw value for enum cases.") + case .dictionary: + fatalError("Dictionary is not supported as a raw value for enum cases.") + } + } + + return EnumCaseDeclSyntax( + caseKeyword: caseKeyword, + elements: EnumCaseElementListSyntax([ + EnumCaseElementSyntax( + leadingTrivia: .space, + _: nil, + name: identifier, + _: nil, + parameterClause: parameterClause, + _: nil, + rawValue: initializer, + _: nil, + trailingComma: nil, + trailingTrivia: .newline + ) + ]) + ) + } +} diff --git a/Sources/SyntaxKit/EnumCase.swift b/Sources/SyntaxKit/EnumCase.swift index 61c09ee..9a17724 100644 --- a/Sources/SyntaxKit/EnumCase.swift +++ b/Sources/SyntaxKit/EnumCase.swift @@ -31,8 +31,15 @@ import SwiftSyntax /// A Swift `case` declaration inside an `enum`. public struct EnumCase: CodeBlock { - private let name: String - private var literalValue: Literal? + internal let name: String + internal var literalValue: Literal? + internal var associatedValues: [(name: String, type: String)] = [] + + /// The name of the enum case. + public var caseName: String { name } + + /// The associated values for the enum case, if any. + public var caseAssociatedValues: [(name: String, type: String)] { associatedValues } /// Creates a `case` declaration. /// - Parameter name: The name of the case. @@ -41,6 +48,17 @@ public struct EnumCase: CodeBlock { self.literalValue = nil } + /// Sets the associated value for the case. + /// - Parameters: + /// - name: The name of the associated value. + /// - type: The type of the associated value. + /// - Returns: A copy of the case with the associated value set. + public func associatedValue(_ name: String, type: String) -> Self { + var copy = self + copy.associatedValues.append((name: name, type: type)) + return copy + } + /// Sets the raw value of the case to a Literal. /// - Parameter value: The literal value. /// - Returns: A copy of the case with the raw value set. @@ -71,74 +89,50 @@ public struct EnumCase: CodeBlock { self.equals(.float(value)) } - public var syntax: SyntaxProtocol { - let caseKeyword = TokenSyntax.keyword(.case, trailingTrivia: .space) - let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) - - var initializer: InitializerClauseSyntax? - if let literal = literalValue { - switch literal { - case .string(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) - ]), - closingQuote: .stringQuoteToken() - ) - ) - case .float(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: FloatLiteralExprSyntax(literal: .floatLiteral(String(value))) - ) - case .integer(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(value))) - ) - case .nil: - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) - ) - case .boolean(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) - ) - case .ref(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: DeclReferenceExprSyntax(baseName: .identifier(value)) - ) - case .tuple: - fatalError("Tuple is not supported as a raw value for enum cases.") - case .array: - fatalError("Array is not supported as a raw value for enum cases.") - case .dictionary: - fatalError("Dictionary is not supported as a raw value for enum cases.") - } + /// Returns a SwiftSyntax expression for this enum case (for use in throw/return/etc). + public var asExpressionSyntax: ExprSyntax { + let parts = name.split(separator: ".", maxSplits: 1) + let base: ExprSyntax? = + parts.count == 2 + ? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(String(parts[0])))) + : nil + let caseName = parts.count == 2 ? String(parts[1]) : name + let memberAccess = MemberAccessExprSyntax( + base: base, + dot: .periodToken(), + name: .identifier(caseName) + ) + if !associatedValues.isEmpty { + let tuple = TupleExprSyntax( + leftParen: .leftParenToken(), + elements: TupleExprElementListSyntax( + associatedValues.map { associated in + TupleExprElementSyntax( + label: nil, + colon: nil, + expression: ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier(associated.name))), + trailingComma: nil + ) + } + ), + rightParen: .rightParenToken() + ) + return ExprSyntax( + FunctionCallExprSyntax( + calledExpression: ExprSyntax(memberAccess), + leftParen: tuple.leftParen, + arguments: tuple.elements, + rightParen: tuple.rightParen + )) + } else { + return ExprSyntax(memberAccess) } + } - return EnumCaseDeclSyntax( - caseKeyword: caseKeyword, - elements: EnumCaseElementListSyntax([ - EnumCaseElementSyntax( - leadingTrivia: .space, - _: nil, - name: identifier, - _: nil, - parameterClause: nil, - _: nil, - rawValue: initializer, - _: nil, - trailingComma: nil, - trailingTrivia: .newline - ) - ]) - ) + /// Returns the expression syntax for this enum case. + /// This is the preferred method when using EnumCase in expression contexts. + public var exprSyntax: ExprSyntax { + asExpressionSyntax } } diff --git a/Sources/SyntaxKit/Function+EffectSpecifiers.swift b/Sources/SyntaxKit/Function+EffectSpecifiers.swift new file mode 100644 index 0000000..f985770 --- /dev/null +++ b/Sources/SyntaxKit/Function+EffectSpecifiers.swift @@ -0,0 +1,88 @@ +// +// Function+EffectSpecifiers.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Function { + /// Builds the effect specifiers (async / throws) for the function. + internal func buildEffectSpecifiers() -> FunctionEffectSpecifiersSyntax? { + switch effect { + case .none: + return nil + case .throws(let isRethrows, let errorType): + let throwsSpecifier = buildThrowsSpecifier(isRethrows: isRethrows) + if let errorType = errorType { + return FunctionEffectSpecifiersSyntax( + asyncSpecifier: nil, + throwsClause: buildThrowsClause(throwsSpecifier: throwsSpecifier, errorType: errorType) + ) + } else { + return FunctionEffectSpecifiersSyntax( + asyncSpecifier: nil, + throwsSpecifier: throwsSpecifier + ) + } + case .async: + return FunctionEffectSpecifiersSyntax( + asyncSpecifier: .keyword(.async, leadingTrivia: .space, trailingTrivia: .space), + throwsSpecifier: nil + ) + case .asyncThrows(let isRethrows, let errorType): + let throwsSpecifier = buildThrowsSpecifier(isRethrows: isRethrows) + if let errorType = errorType { + return FunctionEffectSpecifiersSyntax( + asyncSpecifier: .keyword(.async, leadingTrivia: .space, trailingTrivia: .space), + throwsClause: buildThrowsClause(throwsSpecifier: throwsSpecifier, errorType: errorType) + ) + } else { + return FunctionEffectSpecifiersSyntax( + asyncSpecifier: .keyword(.async, leadingTrivia: .space, trailingTrivia: .space), + throwsSpecifier: throwsSpecifier + ) + } + } + } + + /// Builds the throws specifier token. + private func buildThrowsSpecifier(isRethrows: Bool) -> TokenSyntax { + .keyword(isRethrows ? .rethrows : .throws, leadingTrivia: .space) + } + + /// Builds the throws clause with error type. + private func buildThrowsClause(throwsSpecifier: TokenSyntax, errorType: String) + -> ThrowsClauseSyntax + { + ThrowsClauseSyntax( + throwsSpecifier: throwsSpecifier, + leftParen: .leftParenToken(), + type: IdentifierTypeSyntax(name: .identifier(errorType)), + rightParen: .rightParenToken() + ) + } +} diff --git a/Sources/SyntaxKit/Function+Effects.swift b/Sources/SyntaxKit/Function+Effects.swift new file mode 100644 index 0000000..ff6766c --- /dev/null +++ b/Sources/SyntaxKit/Function+Effects.swift @@ -0,0 +1,91 @@ +// +// Function+Effects.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Function { + /// Function effect specifiers (async/throws combinations) + internal enum Effect { + case none + /// synchronous effect specifier: throws or rethrows + case `throws`(isRethrows: Bool, errorType: String?) + case async + /// combined async and throws/rethrows + case asyncThrows(isRethrows: Bool, errorType: String?) + } + + /// Marks the function as `throws` or `rethrows`. + /// - Parameter rethrows: Pass `true` to emit `rethrows` instead of `throws`. + public func `throws`(isRethrows: Bool = false) -> Self { + var copy = self + switch effect { + case .async: + copy.effect = .asyncThrows(isRethrows: isRethrows, errorType: nil) + default: + copy.effect = .throws(isRethrows: isRethrows, errorType: nil) + } + return copy + } + + /// Marks the function as `throws` with a specific error type. + /// - Parameter errorType: The error type to specify in the throws clause. + public func `throws`(_ errorType: String) -> Self { + var copy = self + switch effect { + case .async: + copy.effect = .asyncThrows(isRethrows: false, errorType: errorType) + default: + copy.effect = .throws(isRethrows: false, errorType: errorType) + } + return copy + } + + /// Marks the function as `async`. + public func async() -> Self { + var copy = self + copy.effect = .async + return copy + } + + /// Marks the function as `async throws` or `async rethrows`. + /// - Parameter rethrows: Pass `true` to emit `async rethrows`. + public func asyncThrows(isRethrows: Bool = false) -> Self { + var copy = self + copy.effect = .asyncThrows(isRethrows: isRethrows, errorType: nil) + return copy + } + + /// Marks the function as `async throws` with a specific error type. + /// - Parameter errorType: The error type to specify in the throws clause. + public func asyncThrows(_ errorType: String) -> Self { + var copy = self + copy.effect = .asyncThrows(isRethrows: false, errorType: errorType) + return copy + } +} diff --git a/Sources/SyntaxKit/Function+Modifiers.swift b/Sources/SyntaxKit/Function+Modifiers.swift new file mode 100644 index 0000000..cb1a734 --- /dev/null +++ b/Sources/SyntaxKit/Function+Modifiers.swift @@ -0,0 +1,59 @@ +// +// Function+Modifiers.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Function { + /// Marks the function as `static`. + /// - Returns: A copy of the function marked as `static`. + public func `static`() -> Self { + var copy = self + copy.isStatic = true + return copy + } + + /// Marks the function as `mutating`. + /// - Returns: A copy of the function marked as `mutating`. + public func mutating() -> Self { + var copy = self + copy.isMutating = true + return copy + } + + /// Adds an attribute to the function declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the function with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } +} diff --git a/Sources/SyntaxKit/Function+Syntax.swift b/Sources/SyntaxKit/Function+Syntax.swift new file mode 100644 index 0000000..5c03603 --- /dev/null +++ b/Sources/SyntaxKit/Function+Syntax.swift @@ -0,0 +1,195 @@ +// +// Function+Syntax.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Function { + /// The syntax representation of this function. + public var syntax: SyntaxProtocol { + let funcKeyword = TokenSyntax.keyword(.func, trailingTrivia: .space) + let identifier = TokenSyntax.identifier(name) + + // Build parameter list + let paramList = FunctionParameterListSyntax( + parameters.enumerated().compactMap { index, param in + // Skip empty placeholders (possible in some builder scenarios) + guard !param.name.isEmpty || param.defaultValue != nil else { return nil } + + // Attributes for parameter + let paramAttributes = buildAttributeList(from: param.attributes) + + let firstNameLeading: Trivia = paramAttributes.isEmpty ? [] : .space + + // Determine first & second names + let firstNameToken: TokenSyntax + let secondNameToken: TokenSyntax? + + if param.isUnnamed { + firstNameToken = .wildcardToken(leadingTrivia: firstNameLeading, trailingTrivia: .space) + secondNameToken = .identifier(param.name) + } else if let label = param.label { + firstNameToken = .identifier( + label, leadingTrivia: firstNameLeading, trailingTrivia: .space) + secondNameToken = .identifier(param.name) + } else { + firstNameToken = .identifier( + param.name, leadingTrivia: firstNameLeading, trailingTrivia: .space) + secondNameToken = nil + } + + var paramSyntax = FunctionParameterSyntax( + attributes: paramAttributes, + firstName: firstNameToken, + secondName: secondNameToken, + colon: .colonToken(trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(param.type)), + defaultValue: param.defaultValue.map { + InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier($0))) + ) + } + ) + if index < parameters.count - 1 { + paramSyntax = paramSyntax.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return paramSyntax + }) + + // Build return type if specified + var returnClause: ReturnClauseSyntax? + if let returnType = returnType { + returnClause = ReturnClauseSyntax( + arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(returnType)) + ) + } + + // Build function body + let bodyBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax( + body.compactMap { + var item: CodeBlockItemSyntax? + if let decl = $0.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = $0.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = $0.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + }), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + // Build effect specifiers (async / throws) + let effectSpecifiers = buildEffectSpecifiers() + + // Build modifiers + var modifiers: DeclModifierListSyntax = [] + if isStatic { + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) + ]) + } + if isMutating { + modifiers = DeclModifierListSyntax( + modifiers + [ + DeclModifierSyntax(name: .keyword(.mutating, trailingTrivia: .space)) + ]) + } + + return FunctionDeclSyntax( + attributes: buildAttributeList(from: attributes), + modifiers: modifiers, + funcKeyword: funcKeyword, + name: identifier, + genericParameterClause: nil, + signature: FunctionSignatureSyntax( + parameterClause: FunctionParameterClauseSyntax( + leftParen: .leftParenToken(), + parameters: paramList, + rightParen: .rightParenToken() + ), + effectSpecifiers: effectSpecifiers, + returnClause: returnClause + ), + genericWhereClause: nil, + body: bodyBlock + ) + } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + + return AttributeListSyntax(attributeElements) + } +} diff --git a/Sources/SyntaxKit/Function.swift b/Sources/SyntaxKit/Function.swift index 8afa892..655970b 100644 --- a/Sources/SyntaxKit/Function.swift +++ b/Sources/SyntaxKit/Function.swift @@ -31,13 +31,14 @@ import SwiftSyntax /// A Swift `func` declaration. public struct Function: CodeBlock { - private let name: String - private let parameters: [Parameter] - private let returnType: String? - private let body: [CodeBlock] - private var isStatic: Bool = false - private var isMutating: Bool = false - private var attributes: [AttributeInfo] = [] + internal let name: String + internal let parameters: [Parameter] + internal let returnType: String? + internal let body: [CodeBlock] + internal var isStatic: Bool = false + internal var isMutating: Bool = false + internal var effect: Effect = .none + internal var attributes: [AttributeInfo] = [] /// Creates a `func` declaration. /// - Parameters: @@ -71,179 +72,19 @@ public struct Function: CodeBlock { self.body = content() } - /// Marks the function as `static`. - /// - Returns: A copy of the function marked as `static`. - public func `static`() -> Self { - var copy = self - copy.isStatic = true - return copy - } - - /// Marks the function as `mutating`. - /// - Returns: A copy of the function marked as `mutating`. - public func mutating() -> Self { - var copy = self - copy.isMutating = true - return copy - } - - /// Adds an attribute to the function declaration. + /// Creates a `func` declaration with parameters and body using the DSL syntax. /// - Parameters: - /// - attribute: The attribute name (without the @ symbol). - /// - arguments: The arguments for the attribute, if any. - /// - Returns: A copy of the function with the attribute added. - public func attribute(_ attribute: String, arguments: [String] = []) -> Self { - var copy = self - copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) - return copy - } - - public var syntax: SyntaxProtocol { - let funcKeyword = TokenSyntax.keyword(.func, trailingTrivia: .space) - let identifier = TokenSyntax.identifier(name) - - // Build parameter list - let paramList: FunctionParameterListSyntax - if parameters.isEmpty { - paramList = FunctionParameterListSyntax([]) - } else { - paramList = FunctionParameterListSyntax( - parameters.enumerated().compactMap { index, param in - guard !param.name.isEmpty, !param.type.isEmpty else { return nil } - - // Build parameter attributes - let paramAttributes = buildAttributeList(from: param.attributes) - - // Determine spacing for firstName based on whether attributes are present - let firstNameLeadingTrivia: Trivia = paramAttributes.isEmpty ? [] : .space - - var paramSyntax = FunctionParameterSyntax( - attributes: paramAttributes, - firstName: param.isUnnamed - ? .wildcardToken(leadingTrivia: firstNameLeadingTrivia, trailingTrivia: .space) - : .identifier(param.name, leadingTrivia: firstNameLeadingTrivia), - secondName: param.isUnnamed ? .identifier(param.name) : nil, - colon: .colonToken(trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(param.type)), - defaultValue: param.defaultValue.map { - InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier($0))) - ) - } - ) - if index < parameters.count - 1 { - paramSyntax = paramSyntax.with(\.trailingComma, .commaToken(trailingTrivia: .space)) - } - return paramSyntax - }) - } - - // Build return type if specified - var returnClause: ReturnClauseSyntax? - if let returnType = returnType { - returnClause = ReturnClauseSyntax( - arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(returnType)) - ) - } - - // Build function body - let bodyBlock = CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - statements: CodeBlockItemListSyntax( - body.compactMap { - var item: CodeBlockItemSyntax? - if let decl = $0.syntax.as(DeclSyntax.self) { - item = CodeBlockItemSyntax(item: .decl(decl)) - } else if let expr = $0.syntax.as(ExprSyntax.self) { - item = CodeBlockItemSyntax(item: .expr(expr)) - } else if let stmt = $0.syntax.as(StmtSyntax.self) { - item = CodeBlockItemSyntax(item: .stmt(stmt)) - } - return item?.with(\.trailingTrivia, .newline) - }), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - - // Build modifiers - var modifiers: DeclModifierListSyntax = [] - if isStatic { - modifiers = DeclModifierListSyntax([ - DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) - ]) - } - if isMutating { - modifiers = DeclModifierListSyntax( - modifiers + [ - DeclModifierSyntax(name: .keyword(.mutating, trailingTrivia: .space)) - ]) - } - - return FunctionDeclSyntax( - attributes: buildAttributeList(from: attributes), - modifiers: modifiers, - funcKeyword: funcKeyword, - name: identifier, - genericParameterClause: nil, - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax( - leftParen: .leftParenToken(), - parameters: paramList, - rightParen: .rightParenToken() - ), - effectSpecifiers: nil, - returnClause: returnClause - ), - genericWhereClause: nil, - body: bodyBlock - ) - } - - private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { - if attributes.isEmpty { - return AttributeListSyntax([]) - } - - let attributeElements = attributes.map { attributeInfo in - let arguments = attributeInfo.arguments - - var leftParen: TokenSyntax? - var rightParen: TokenSyntax? - var argumentsSyntax: AttributeSyntax.Arguments? - - if !arguments.isEmpty { - leftParen = .leftParenToken() - rightParen = .rightParenToken() - - let argumentList = arguments.map { argument in - DeclReferenceExprSyntax(baseName: .identifier(argument)) - } - - argumentsSyntax = .argumentList( - LabeledExprListSyntax( - argumentList.enumerated().map { index, expr in - var element = LabeledExprSyntax(expression: ExprSyntax(expr)) - if index < argumentList.count - 1 { - element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) - } - return element - } - ) - ) - } - - return AttributeListSyntax.Element( - AttributeSyntax( - atSign: .atSignToken(), - attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), - leftParen: leftParen, - arguments: argumentsSyntax, - rightParen: rightParen - ) - ) - } - - return AttributeListSyntax(attributeElements) + /// - name: The name of the function. + /// - params: A ``ParameterBuilder`` that provides the parameters of the function. + /// - body: A ``CodeBlockBuilder`` that provides the body of the function. + public init( + _ name: String, + @ParameterBuilderResult _ params: () -> [Parameter], + @CodeBlockBuilderResult _ body: () -> [CodeBlock] + ) { + self.name = name + self.parameters = params() + self.returnType = nil + self.body = body() } } diff --git a/Sources/SyntaxKit/Guard.swift b/Sources/SyntaxKit/Guard.swift index 40f194f..b5e9bf5 100644 --- a/Sources/SyntaxKit/Guard.swift +++ b/Sources/SyntaxKit/Guard.swift @@ -36,7 +36,8 @@ public struct Guard: CodeBlock { /// Creates a `guard` statement. /// - Parameters: - /// - condition: A builder that returns one or more ``CodeBlock`` items representing the guard conditions. + /// - condition: A builder that returns one or more ``CodeBlock`` items representing the guard + /// conditions. /// - elseBody: Builder that produces the statements inside the `else` block. public init( @CodeBlockBuilderResult _ condition: () -> [CodeBlock], @@ -87,7 +88,9 @@ public struct Guard: CodeBlock { condition: .expression( ExprSyntax( fromProtocol: block.syntax.as(ExprSyntax.self) - ?? DeclReferenceExprSyntax(baseName: .identifier("")))) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + ) ) return appendComma(element) } @@ -107,13 +110,14 @@ public struct Guard: CodeBlock { } // Automatically append a bare `return` if the user didn't provide a terminating statement. - let containsReturn = elseItems.contains { item in + let containsTerminatingStatement = elseItems.contains { item in if case .stmt(let stmt) = item.item { - return stmt.is(ReturnStmtSyntax.self) + return stmt.is(ReturnStmtSyntax.self) || stmt.is(ThrowStmtSyntax.self) + || stmt.is(BreakStmtSyntax.self) || stmt.is(ContinueStmtSyntax.self) } return false } - if !containsReturn { + if !containsTerminatingStatement { let retStmt = ReturnStmtSyntax(returnKeyword: .keyword(.return)) elseItems.append( CodeBlockItemSyntax(item: .stmt(StmtSyntax(retStmt))).with(\.trailingTrivia, .newline) diff --git a/Sources/SyntaxKit/If.swift b/Sources/SyntaxKit/If.swift index 8d8c4e5..b916df7 100644 --- a/Sources/SyntaxKit/If.swift +++ b/Sources/SyntaxKit/If.swift @@ -107,7 +107,10 @@ public struct If: CodeBlock { statements: CodeBlockItemListSyntax( body.compactMap { var item: CodeBlockItemSyntax? - if let decl = $0.syntax.as(DeclSyntax.self) { + if let enumCase = $0 as? EnumCase { + // Handle EnumCase specially - use expression syntax for enum cases in expressions + item = CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)) + } else if let decl = $0.syntax.as(DeclSyntax.self) { item = CodeBlockItemSyntax(item: .decl(decl)) } else if let expr = $0.syntax.as(ExprSyntax.self) { item = CodeBlockItemSyntax(item: .expr(expr)) @@ -120,7 +123,9 @@ public struct If: CodeBlock { ) // swiftlint:disable:next closure_body_length let elseBlock: IfExprSyntax.ElseBody? = { - guard let elseBlocks = elseBody else { return nil } + guard let elseBlocks = elseBody else { + return nil + } // Build a chained else-if structure if the builder provided If blocks. var current: SyntaxProtocol? @@ -131,7 +136,11 @@ public struct If: CodeBlock { // Leaf `else` – produce a code-block. let stmts = CodeBlockItemListSyntax( thenBlock.body.compactMap { element in - if let decl = element.syntax.as(DeclSyntax.self) { + if let enumCase = element as? EnumCase { + // Handle EnumCase specially - use expression syntax for enum cases in expressions + return CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)).with( + \.trailingTrivia, .newline) + } else if let decl = element.syntax.as(DeclSyntax.self) { return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) } else if let expr = element.syntax.as(ExprSyntax.self) { return CodeBlockItemSyntax(item: .expr(expr)).with(\.trailingTrivia, .newline) @@ -169,7 +178,10 @@ public struct If: CodeBlock { default: // Treat any other CodeBlock as part of a final code-block let item: CodeBlockItemSyntax? - if let decl = block.syntax.as(DeclSyntax.self) { + if let enumCase = block as? EnumCase { + // Handle EnumCase specially - use expression syntax for enum cases in expressions + item = CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)) + } else if let decl = block.syntax.as(DeclSyntax.self) { item = CodeBlockItemSyntax(item: .decl(decl)) } else if let expr = block.syntax.as(ExprSyntax.self) { item = CodeBlockItemSyntax(item: .expr(expr)) diff --git a/Sources/SyntaxKit/Infix.swift b/Sources/SyntaxKit/Infix.swift index ad18e0d..82ce259 100644 --- a/Sources/SyntaxKit/Infix.swift +++ b/Sources/SyntaxKit/Infix.swift @@ -68,3 +68,53 @@ public struct Infix: CodeBlock { ) } } + +// MARK: - Operator Overloads for Infix Expressions + +/// Creates a greater-than comparison expression. +/// - Parameters: +/// - lhs: The left-hand side expression. +/// - rhs: The right-hand side expression. +/// - Returns: An infix expression representing `lhs > rhs`. +public func > (lhs: CodeBlock, rhs: CodeBlock) -> Infix { + Infix(">") { + lhs + rhs + } +} + +/// Creates a less-than comparison expression. +/// - Parameters: +/// - lhs: The left-hand side expression. +/// - rhs: The right-hand side expression. +/// - Returns: An infix expression representing `lhs < rhs`. +public func < (lhs: CodeBlock, rhs: CodeBlock) -> Infix { + Infix("<") { + lhs + rhs + } +} + +/// Creates an equality comparison expression. +/// - Parameters: +/// - lhs: The left-hand side expression. +/// - rhs: The right-hand side expression. +/// - Returns: An infix expression representing `lhs == rhs`. +public func == (lhs: CodeBlock, rhs: CodeBlock) -> Infix { + Infix("==") { + lhs + rhs + } +} + +/// Creates an inequality comparison expression. +/// - Parameters: +/// - lhs: The left-hand side expression. +/// - rhs: The right-hand side expression. +/// - Returns: An infix expression representing `lhs != rhs`. +public func != (lhs: CodeBlock, rhs: CodeBlock) -> Infix { + Infix("!=") { + lhs + rhs + } +} diff --git a/Sources/SyntaxKit/Init.swift b/Sources/SyntaxKit/Init.swift index fb9000e..acf8122 100644 --- a/Sources/SyntaxKit/Init.swift +++ b/Sources/SyntaxKit/Init.swift @@ -30,10 +30,17 @@ import SwiftSyntax /// An initializer expression. -public struct Init: CodeBlock, ExprCodeBlock { +public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { private let type: String private let parameters: [ParameterExp] + /// Creates an initializer expression with no parameters. + /// - Parameter type: The type to initialize. + public init(_ type: String) { + self.type = type + self.parameters = [] + } + /// Creates an initializer expression. /// - Parameters: /// - type: The type to initialize. @@ -66,4 +73,14 @@ public struct Init: CodeBlock, ExprCodeBlock { public var syntax: SyntaxProtocol { exprSyntax } + + // MARK: - LiteralValue Conformance + + public var typeName: String { + type + } + + public var literalString: String { + "\(type)()" + } } diff --git a/Sources/SyntaxKit/Line.swift b/Sources/SyntaxKit/Line.swift index 3017ae6..5127453 100644 --- a/Sources/SyntaxKit/Line.swift +++ b/Sources/SyntaxKit/Line.swift @@ -27,6 +27,27 @@ // OTHER DEALINGS IN THE SOFTWARE. // +/// obtaining a copy of this software and associated documentation +/// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + import SwiftSyntax /// Represents a single comment line that can be attached to a syntax node. diff --git a/Sources/SyntaxKit/Literal+ExprCodeBlock.swift b/Sources/SyntaxKit/Literal+ExprCodeBlock.swift index 8e96d14..8b74e74 100644 --- a/Sources/SyntaxKit/Literal+ExprCodeBlock.swift +++ b/Sources/SyntaxKit/Literal+ExprCodeBlock.swift @@ -32,6 +32,7 @@ import SwiftSyntax // MARK: - ExprCodeBlock conformance extension Literal: ExprCodeBlock { + /// The expression syntax representation of this literal. public var exprSyntax: ExprSyntax { switch self { case .string(let value): diff --git a/Sources/SyntaxKit/Parameter.swift b/Sources/SyntaxKit/Parameter.swift index 3046692..a5fa4a7 100644 --- a/Sources/SyntaxKit/Parameter.swift +++ b/Sources/SyntaxKit/Parameter.swift @@ -33,10 +33,20 @@ import SwiftSyntax /// A parameter for a function or initializer. public struct Parameter: CodeBlock { + /// The internal parameter name that is visible inside the function body. internal let name: String + + /// The external argument label (first name) shown at call-sites. + /// If `nil`, the label is identical to the internal name (single-name parameter). + /// If the label is the underscore character "_", the parameter is treated as unnamed. + internal let label: String? + internal let type: String internal let defaultValue: String? - internal let isUnnamed: Bool + + /// Convenience flag – true when the parameter uses the underscore label. + internal var isUnnamed: Bool { label == "_" } + internal var attributes: [AttributeInfo] = [] /// Creates a parameter for a function or initializer. @@ -45,20 +55,15 @@ public struct Parameter: CodeBlock { /// - type: The type of the parameter. /// - defaultValue: The default value of the parameter, if any. /// - isUnnamed: A Boolean value that indicates whether the parameter is unnamed. - public init(name: String, type: String, defaultValue: String? = nil, isUnnamed: Bool = false) { - self.name = name - self.type = type - self.defaultValue = defaultValue - self.isUnnamed = isUnnamed - } + // NOTE: The previous initializer that accepted an `isUnnamed` flag has been replaced. /// Creates an unlabeled parameter for function calls or initializers. /// - Parameter value: The value of the parameter. public init(unlabeled value: String) { self.name = "" + self.label = "_" self.type = "" self.defaultValue = value - self.isUnnamed = true } /// Adds an attribute to the parameter declaration. @@ -73,20 +78,64 @@ public struct Parameter: CodeBlock { } public var syntax: SyntaxProtocol { - // Not used for function signature, but for call sites (Init, etc.) + let callLabel = label ?? name + if let defaultValue = defaultValue { return LabeledExprSyntax( - label: .identifier(name), + label: .identifier(callLabel), colon: .colonToken(), expression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(defaultValue))) ) } else { return LabeledExprSyntax( - label: .identifier(name), + label: .identifier(callLabel), colon: .colonToken(), expression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) ) } - // Note: If you want to support attributes in parameter syntax, you would need to update the function signature generation in Function.swift to use these attributes. + // Note: If you want to support attributes in parameter syntax, you would need to + // update the function signature generation in Function.swift to use these attributes. + } + + /// Creates a single-name parameter (same label and internal name). + public init(name: String, type: String, defaultValue: String? = nil) { + self.name = name + self.label = nil + self.type = type + self.defaultValue = defaultValue + } + + /// Creates a two-name parameter where the external label differs from the internal name. + /// Example: `Parameter("value", labeled: "forKey", type: "String")` maps to + /// `forKey value: String` in the generated Swift. + public init( + _ internalName: String, + labeled externalLabel: String, + type: String, + defaultValue: String? = nil + ) { + self.name = internalName + self.label = externalLabel + self.type = type + self.defaultValue = defaultValue + } + + /// Creates an unlabeled (anonymous) parameter using the underscore label. + public init(unlabeled internalName: String, type: String, defaultValue: String? = nil) { + self.name = internalName + self.label = "_" + self.type = type + self.defaultValue = defaultValue + } + + /// Deprecated: retains source compatibility with earlier API that used an `isUnnamed` flag. + /// Prefer `Parameter(unlabeled:type:)` or the new labelled initialisers. + @available(*, deprecated, message: "Use Parameter(unlabeled:type:) or Parameter(_:labeled:type:)") + public init(name: String, type: String, defaultValue: String? = nil, isUnnamed: Bool) { + if isUnnamed { + self.init(unlabeled: name, type: type, defaultValue: defaultValue) + } else { + self.init(name: name, type: type, defaultValue: defaultValue) + } } } diff --git a/Sources/SyntaxKit/SwitchCase.swift b/Sources/SyntaxKit/SwitchCase.swift index ff7a3d6..0b579cc 100644 --- a/Sources/SyntaxKit/SwitchCase.swift +++ b/Sources/SyntaxKit/SwitchCase.swift @@ -36,7 +36,8 @@ public struct SwitchCase: CodeBlock { /// Creates a `case` for a `switch` statement. /// - Parameters: - /// - patterns: The patterns to match for the case. Can be `PatternConvertible`, `CodeBlock`, or `SwitchLet` for value binding. + /// - patterns: The patterns to match for the case. Can be `PatternConvertible`, + /// `CodeBlock`, or `SwitchLet` for value binding. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. public init(_ patterns: Any..., @CodeBlockBuilderResult content: () -> [CodeBlock]) { self.patterns = patterns diff --git a/Sources/SyntaxKit/Throw.swift b/Sources/SyntaxKit/Throw.swift new file mode 100644 index 0000000..e85abbb --- /dev/null +++ b/Sources/SyntaxKit/Throw.swift @@ -0,0 +1,57 @@ +// +// Throw.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// A Swift `throw` statement. +public struct Throw: CodeBlock { + private let expr: CodeBlock + + public init(_ expr: CodeBlock) { + self.expr = expr + } + + public var syntax: SyntaxProtocol { + let expression: ExprSyntax + if let enumCase = expr as? EnumCase { + expression = enumCase.asExpressionSyntax + } else { + expression = + expr.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } + return StmtSyntax( + ThrowStmtSyntax( + throwKeyword: .keyword(.throw, trailingTrivia: .space), + expression: expression + ) + ) + } +} diff --git a/Sources/SyntaxKit/Tuple.swift b/Sources/SyntaxKit/Tuple.swift index 03bab7f..622673e 100644 --- a/Sources/SyntaxKit/Tuple.swift +++ b/Sources/SyntaxKit/Tuple.swift @@ -31,7 +31,9 @@ import SwiftSyntax /// A tuple expression, e.g. `(a, b, c)`. public struct Tuple: CodeBlock { - private let elements: [CodeBlock] + internal let elements: [CodeBlock] + private var isAsync: Bool = false + private var isThrowing: Bool = false /// Creates a tuple expression comprising the supplied elements. /// - Parameter content: A ``CodeBlockBuilder`` producing the tuple elements **in order**. @@ -53,6 +55,30 @@ public struct Tuple: CodeBlock { TuplePatternCodeBlock(elements: elements) } + /// Marks this tuple as async. + /// - Returns: A copy of the tuple marked as async. + public func async() -> Self { + var copy = self + copy.isAsync = true + return copy + } + + /// Marks this tuple as await. + /// - Returns: A copy of the tuple marked as await. + public func await() -> Self { + var copy = self + copy.isAsync = true + return copy + } + + /// Marks this tuple as throwing. + /// - Returns: A copy of the tuple marked as throwing. + public func throwing() -> Self { + var copy = self + copy.isThrowing = true + return copy + } + public var syntax: SyntaxProtocol { guard !elements.isEmpty else { fatalError("Tuple must contain at least one element.") @@ -60,7 +86,20 @@ public struct Tuple: CodeBlock { let list = TupleExprElementListSyntax( elements.enumerated().map { index, block in - let elementExpr = block.expr + let elementExpr: ExprSyntax + if isAsync { + // For async tuples, generate async let syntax for each element + // This assumes the block is a function call or expression that can be awaited + elementExpr = ExprSyntax( + AwaitExprSyntax( + awaitKeyword: .keyword(.await, trailingTrivia: .space), + expression: block.expr + ) + ) + } else { + elementExpr = block.expr + } + return TupleExprElementSyntax( label: nil, colon: nil, @@ -78,6 +117,15 @@ public struct Tuple: CodeBlock { ) ) - return tupleExpr + if isThrowing { + return ExprSyntax( + TryExprSyntax( + tryKeyword: .keyword(.try, trailingTrivia: .space), + expression: tupleExpr + ) + ) + } else { + return tupleExpr + } } } diff --git a/Sources/SyntaxKit/TupleAssignment+AsyncSet.swift b/Sources/SyntaxKit/TupleAssignment+AsyncSet.swift new file mode 100644 index 0000000..f28bd41 --- /dev/null +++ b/Sources/SyntaxKit/TupleAssignment+AsyncSet.swift @@ -0,0 +1,95 @@ +// +// TupleAssignment+AsyncSet.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension TupleAssignment { + internal enum AsyncSet { + static func tuplePattern(elements: [String]) -> PatternSyntax { + let patternElements = TuplePatternElementListSyntax( + elements.enumerated().map { index, element in + TuplePatternElementSyntax( + label: nil, + colon: nil, + pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(element))), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + return PatternSyntax( + TuplePatternSyntax( + leftParen: .leftParenToken(), + elements: patternElements, + rightParen: .rightParenToken() + ) + ) + } + + static func tupleExpr(tuple: Tuple) -> ExprSyntax { + ExprSyntax( + TupleExprSyntax( + leftParen: .leftParenToken(), + elements: LabeledExprListSyntax( + tuple.elements.enumerated().map { index, block in + LabeledExprSyntax( + label: nil, + colon: nil, + expression: block.expr, + trailingComma: index < tuple.elements.count - 1 + ? .commaToken(trailingTrivia: .space) : nil + ) + } + ), + rightParen: .rightParenToken() + ) + ) + } + + static func valueExpr(tupleExpr: ExprSyntax, isThrowing: Bool) -> ExprSyntax { + isThrowing + ? ExprSyntax( + TryExprSyntax( + tryKeyword: .keyword(.try, trailingTrivia: .space), + expression: ExprSyntax( + AwaitExprSyntax( + awaitKeyword: .keyword(.await, trailingTrivia: .space), + expression: tupleExpr + ) + ) + ) + ) + : ExprSyntax( + AwaitExprSyntax( + awaitKeyword: .keyword(.await, trailingTrivia: .space), + expression: tupleExpr + ) + ) + } + } +} diff --git a/Sources/SyntaxKit/TupleAssignment.swift b/Sources/SyntaxKit/TupleAssignment.swift new file mode 100644 index 0000000..10da5e6 --- /dev/null +++ b/Sources/SyntaxKit/TupleAssignment.swift @@ -0,0 +1,207 @@ +// +// TupleAssignment.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// A tuple assignment statement for destructuring multiple values. +public struct TupleAssignment: CodeBlock { + private let elements: [String] + private let value: CodeBlock + private var isAsync: Bool = false + private var isThrowing: Bool = false + private var isAsyncSet: Bool = false + + /// Creates a tuple destructuring declaration. + /// - Parameters: + /// - elements: The names of the variables to destructure into. + /// - value: The expression to destructure. + public init(_ elements: [String], equals value: CodeBlock) { + self.elements = elements + self.value = value + } + + /// Marks this destructuring as async. + /// - Returns: A copy of the destructuring marked as async. + public func async() -> Self { + var copy = self + copy.isAsync = true + return copy + } + + /// Marks this destructuring as throwing. + /// - Returns: A copy of the destructuring marked as throwing. + public func throwing() -> Self { + var copy = self + copy.isThrowing = true + return copy + } + + /// Marks this destructuring as concurrent async (async let set). + /// - Returns: A copy of the destructuring marked as async set. + public func asyncSet() -> Self { + var copy = self + copy.isAsyncSet = true + return copy + } + + /// The syntax representation of this tuple assignment. + public var syntax: SyntaxProtocol { + if isAsyncSet { + return generateAsyncSetSyntax() + } + return generateRegularSyntax() + } + + /// Generates the asyncSet tuple assignment syntax. + private func generateAsyncSetSyntax() -> SyntaxProtocol { + // Generate a single async let tuple destructuring assignment + guard let tuple = value as? Tuple, elements.count == tuple.elements.count else { + fatalError( + "asyncSet requires a Tuple value with the same number of elements as the assignment.") + } + + // Use helpers from AsyncSet + let tuplePattern = AsyncSet.tuplePattern(elements: elements) + let tupleExpr = AsyncSet.tupleExpr(tuple: tuple) + let valueExpr = AsyncSet.valueExpr(tupleExpr: tupleExpr, isThrowing: isThrowing) + + // Build the async let declaration + let asyncLet = CodeBlockItemSyntax( + item: CodeBlockItemSyntax.Item.decl( + DeclSyntax( + VariableDeclSyntax( + modifiers: DeclModifierListSyntax([ + DeclModifierSyntax( + name: .keyword(.async, trailingTrivia: .space) + ) + ]), + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + bindings: PatternBindingListSyntax([ + PatternBindingSyntax( + pattern: tuplePattern, + initializer: InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: valueExpr + ) + ) + ]) + ) + ) + ) + ) + + return CodeBlockSyntax( + leftBrace: .leftBraceToken(), + statements: CodeBlockItemListSyntax([asyncLet]), + rightBrace: .rightBraceToken() + ) + } + + /// Generates the regular tuple assignment syntax. + private func generateRegularSyntax() -> SyntaxProtocol { + // Build the tuple pattern + let patternElements = TuplePatternElementListSyntax( + elements.enumerated().map { index, element in + TuplePatternElementSyntax( + label: nil, + colon: nil, + pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(element))), + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ) + } + ) + + let tuplePattern = PatternSyntax( + TuplePatternSyntax( + leftParen: .leftParenToken(), + elements: patternElements, + rightParen: .rightParenToken() + ) + ) + + // Build the value expression + let valueExpr = buildValueExpression() + + // Build the variable declaration + return VariableDeclSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + bindings: PatternBindingListSyntax([ + PatternBindingSyntax( + pattern: tuplePattern, + initializer: InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: valueExpr + ) + ) + ]) + ) + } + + /// Builds the value expression based on async and throwing flags. + private func buildValueExpression() -> ExprSyntax { + let baseExpr = + value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + + if isThrowing { + if isAsync { + return ExprSyntax( + TryExprSyntax( + tryKeyword: .keyword(.try, trailingTrivia: .space), + expression: ExprSyntax( + AwaitExprSyntax( + awaitKeyword: .keyword(.await, trailingTrivia: .space), + expression: baseExpr + ) + ) + ) + ) + } else { + return ExprSyntax( + TryExprSyntax( + tryKeyword: .keyword(.try, trailingTrivia: .space), + expression: baseExpr + ) + ) + } + } else { + if isAsync { + return ExprSyntax( + AwaitExprSyntax( + awaitKeyword: .keyword(.await, trailingTrivia: .space), + expression: baseExpr + ) + ) + } else { + return baseExpr + } + } + } +} diff --git a/Sources/SyntaxKit/TupleLiteral.swift b/Sources/SyntaxKit/TupleLiteral.swift index 58b8fc4..ecf3444 100644 --- a/Sources/SyntaxKit/TupleLiteral.swift +++ b/Sources/SyntaxKit/TupleLiteral.swift @@ -29,7 +29,7 @@ import Foundation -/// A tuple value that can be used as a literal. +/// A tuple literal value that can be used as a literal. public struct TupleLiteral: LiteralValue { let elements: [Literal?] diff --git a/Sources/SyntaxKit/Variable+Initializers.swift b/Sources/SyntaxKit/Variable+LiteralInitializers.swift similarity index 60% rename from Sources/SyntaxKit/Variable+Initializers.swift rename to Sources/SyntaxKit/Variable+LiteralInitializers.swift index 0799395..a23ed4e 100644 --- a/Sources/SyntaxKit/Variable+Initializers.swift +++ b/Sources/SyntaxKit/Variable+LiteralInitializers.swift @@ -1,5 +1,5 @@ // -// Variable+Initializers.swift +// Variable+LiteralInitializers.swift // SyntaxKit // // Created by Leo Dion. @@ -29,110 +29,9 @@ import Foundation -// MARK: - Variable Initializers +// MARK: - Variable Literal Initializers extension Variable { - /// Creates a `let` or `var` declaration with an explicit type. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - type: The type of the variable. - /// - equals: The initial value expression of the variable, if any. - /// - explicitType: Whether the variable has an explicit type. - public init( - _ kind: VariableKind, name: String, type: String, equals defaultValue: CodeBlock? = nil, - explicitType: Bool? = nil - ) { - let finalExplicitType = explicitType ?? (defaultValue == nil) - self.init( - kind: kind, - name: name, - type: type, - defaultValue: defaultValue, - explicitType: finalExplicitType - ) - } - - /// Creates a `let` or `var` declaration with an explicit type and string literal value. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - type: The type of the variable. - /// - equals: A string literal value. - /// - explicitType: Whether the variable has an explicit type. - public init( - _ kind: VariableKind, name: String, type: String, equals value: String, - explicitType: Bool? = nil - ) { - self.init( - kind: kind, - name: name, - type: type, - defaultValue: Literal.string(value), - explicitType: explicitType ?? true - ) - } - - /// Creates a `let` or `var` declaration with an explicit type and integer literal value. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - type: The type of the variable. - /// - equals: An integer literal value. - /// - explicitType: Whether the variable has an explicit type. - public init( - _ kind: VariableKind, name: String, type: String, equals value: Int, - explicitType: Bool? = nil - ) { - self.init( - kind: kind, - name: name, - type: type, - defaultValue: Literal.integer(value), - explicitType: explicitType ?? true - ) - } - - /// Creates a `let` or `var` declaration with an explicit type and boolean literal value. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - type: The type of the variable. - /// - equals: A boolean literal value. - /// - explicitType: Whether the variable has an explicit type. - public init( - _ kind: VariableKind, name: String, type: String, equals value: Bool, - explicitType: Bool? = nil - ) { - self.init( - kind: kind, - name: name, - type: type, - defaultValue: Literal.boolean(value), - explicitType: explicitType ?? true - ) - } - - /// Creates a `let` or `var` declaration with an explicit type and double literal value. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - type: The type of the variable. - /// - equals: A double literal value. - /// - explicitType: Whether the variable has an explicit type. - public init( - _ kind: VariableKind, name: String, type: String, equals value: Double, - explicitType: Bool? = nil - ) { - self.init( - kind: kind, - name: name, - type: type, - defaultValue: Literal.float(value), - explicitType: explicitType ?? true - ) - } - /// Creates a `let` or `var` declaration with a literal value. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. @@ -154,8 +53,17 @@ extension Variable { defaultValue = Literal.array(array.map { .string($0) }) } else if let dict = value as? [Int: String] { defaultValue = Literal.dictionary(dict.map { (.integer($0.key), .string($0.value)) }) + } else if let dictExpr = value as? DictionaryExpr { + defaultValue = dictExpr + } else if let initExpr = value as? Init { + defaultValue = initExpr + } else if let codeBlock = value as? CodeBlock { + defaultValue = codeBlock } else { - fatalError("Variable: Only Literal types are supported for defaultValue. Got: \(T.self)") + // For any other LiteralValue type that doesn't conform to CodeBlock, + // create a fallback or throw an error + fatalError( + "Variable: Unsupported LiteralValue type that doesn't conform to CodeBlock: \(T.self)") } self.init( diff --git a/Sources/SyntaxKit/Variable+TypedInitializers.swift b/Sources/SyntaxKit/Variable+TypedInitializers.swift new file mode 100644 index 0000000..f5f805b --- /dev/null +++ b/Sources/SyntaxKit/Variable+TypedInitializers.swift @@ -0,0 +1,154 @@ +// +// Variable+TypedInitializers.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +// MARK: - Variable Typed Initializers + +extension Variable { + /// Creates a `let` or `var` declaration with an Init value, inferring the type from the Init. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - equals: An Init expression. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, equals defaultValue: Init, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: nil, // Will be inferred from Init + defaultValue: defaultValue, + explicitType: explicitType ?? false + ) + } + + /// Creates a `let` or `var` declaration with an explicit type. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: The initial value expression of the variable, if any. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals defaultValue: CodeBlock? = nil, + explicitType: Bool? = nil + ) { + let finalExplicitType = explicitType ?? (defaultValue == nil) + self.init( + kind: kind, + name: name, + type: type, + defaultValue: defaultValue, + explicitType: finalExplicitType + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and string literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: A string literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: String, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.string(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and integer literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: An integer literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: Int, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.integer(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and boolean literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: A boolean literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: Bool, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.boolean(value), + explicitType: explicitType ?? true + ) + } + + /// Creates a `let` or `var` declaration with an explicit type and double literal value. + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable. + /// - equals: A double literal value. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, name: String, type: String, equals value: Double, + explicitType: Bool? = nil + ) { + self.init( + kind: kind, + name: name, + type: type, + defaultValue: Literal.float(value), + explicitType: explicitType ?? true + ) + } +} diff --git a/Sources/SyntaxKit/Variable.swift b/Sources/SyntaxKit/Variable.swift index 310b6c2..7b89b5f 100644 --- a/Sources/SyntaxKit/Variable.swift +++ b/Sources/SyntaxKit/Variable.swift @@ -32,31 +32,41 @@ import SwiftSyntax /// A Swift `let` or `var` declaration with an explicit type. public struct Variable: CodeBlock { - let kind: VariableKind - let name: String - let type: String - let defaultValue: CodeBlock? - var isStatic: Bool = false - var attributes: [AttributeInfo] = [] - var explicitType: Bool = false + private let kind: VariableKind + private let name: String + private let type: String + private let defaultValue: CodeBlock? + private var isStatic: Bool = false + private var isAsync: Bool = false + private var attributes: [AttributeInfo] = [] + private var explicitType: Bool = false /// Internal initializer used by extension initializers to reduce code duplication. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - type: The type of the variable. + /// - type: The type of the variable. If nil, will be inferred from defaultValue if it's an Init. /// - defaultValue: The initial value expression of the variable, if any. /// - explicitType: Whether the variable has an explicit type. internal init( kind: VariableKind, name: String, - type: String, + type: String? = nil, defaultValue: CodeBlock? = nil, explicitType: Bool = false ) { self.kind = kind self.name = name - self.type = type + + // If type is provided, use it; otherwise try to infer from defaultValue + if let providedType = type { + self.type = providedType + } else if let initValue = defaultValue as? Init { + self.type = initValue.typeName + } else { + self.type = "" + } + self.defaultValue = defaultValue self.explicitType = explicitType } @@ -69,6 +79,14 @@ public struct Variable: CodeBlock { return copy } + /// Marks the variable as `async`. + /// - Returns: A copy of the variable marked as `async`. + public func async() -> Self { + var copy = self + copy.isAsync = true + return copy + } + /// Adds an attribute to the variable declaration. /// - Parameters: /// - attribute: The attribute name (without the @ symbol). @@ -115,6 +133,13 @@ public struct Variable: CodeBlock { DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) ]) } + if isAsync { + modifiers = DeclModifierListSyntax( + modifiers + [ + DeclModifierSyntax(name: .keyword(.async, trailingTrivia: .space)) + ] + ) + } return VariableDeclSyntax( attributes: buildAttributeList(from: attributes), modifiers: modifiers, @@ -175,4 +200,16 @@ public struct Variable: CodeBlock { return AttributeListSyntax(attributeElements) } + + public enum VariableKind { + case `var` + case `let` + case `static` + case `lazy` + case `weak` + case `unowned` + case `final` + case `override` + case `mutating` + } } diff --git a/Sources/SyntaxKit/VariableDecl.swift b/Sources/SyntaxKit/VariableDecl.swift index 27f1029..3460622 100644 --- a/Sources/SyntaxKit/VariableDecl.swift +++ b/Sources/SyntaxKit/VariableDecl.swift @@ -57,7 +57,8 @@ public struct VariableDecl: CodeBlock { openingQuote: .stringQuoteToken(), segments: StringLiteralSegmentListSyntax([ .stringSegment( - StringSegmentSyntax(content: .stringSegment(String(value.dropFirst().dropLast())))) + StringSegmentSyntax(content: .stringSegment(String(value.dropFirst().dropLast()))) + ) ]), closingQuote: .stringQuoteToken() ) @@ -69,7 +70,8 @@ public struct VariableDecl: CodeBlock { openingQuote: .stringQuoteToken(), segments: StringLiteralSegmentListSyntax([ .stringSegment( - StringSegmentSyntax(content: .stringSegment(value))) + StringSegmentSyntax(content: .stringSegment(value)) + ) ]), closingQuote: .stringQuoteToken() ) diff --git a/Sources/SyntaxKit/VariableExp.swift b/Sources/SyntaxKit/VariableExp.swift index f35234a..6870691 100644 --- a/Sources/SyntaxKit/VariableExp.swift +++ b/Sources/SyntaxKit/VariableExp.swift @@ -42,8 +42,8 @@ public struct VariableExp: CodeBlock, PatternConvertible { /// Accesses a property on the variable. /// - Parameter propertyName: The name of the property to access. /// - Returns: A ``PropertyAccessExp`` that represents the property access. - public func property(_ propertyName: String) -> CodeBlock { - PropertyAccessExp(baseName: name, propertyName: propertyName) + public func property(_ propertyName: String) -> PropertyAccessExp { + PropertyAccessExp(base: self, propertyName: propertyName) } /// Calls a method on the variable. @@ -75,30 +75,79 @@ public struct VariableExp: CodeBlock, PatternConvertible { /// An expression that accesses a property on a base expression. public struct PropertyAccessExp: CodeBlock { - internal let baseName: String + internal let base: CodeBlock internal let propertyName: String /// Creates a property access expression. /// - Parameters: - /// - baseName: The name of the base variable. + /// - base: The base expression. /// - propertyName: The name of the property to access. + public init(base: CodeBlock, propertyName: String) { + self.base = base + self.propertyName = propertyName + } + + /// Convenience initializer for backward compatibility (baseName as String). public init(baseName: String, propertyName: String) { - self.baseName = baseName + self.base = VariableExp(baseName) self.propertyName = propertyName } + /// Accesses a property on the current property access expression (chaining). + /// - Parameter propertyName: The name of the next property to access. + /// - Returns: A new ``PropertyAccessExp`` representing the chained property access. + public func property(_ propertyName: String) -> PropertyAccessExp { + PropertyAccessExp(base: self, propertyName: propertyName) + } + + /// Negates the property access expression. + /// - Returns: A negated property access expression. + public func not() -> CodeBlock { + NegatedPropertyAccessExp(base: self) + } + public var syntax: SyntaxProtocol { - let base = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(baseName))) + let baseSyntax = + base.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) let property = TokenSyntax.identifier(propertyName) return ExprSyntax( MemberAccessExprSyntax( - base: base, + base: baseSyntax, dot: .periodToken(), name: property )) } } +/// An expression that negates a property access. +public struct NegatedPropertyAccessExp: CodeBlock { + internal let base: CodeBlock + + /// Creates a negated property access expression. + /// - Parameter base: The base property access expression. + public init(base: CodeBlock) { + self.base = base + } + + /// Backward compatibility initializer for (baseName, propertyName). + public init(baseName: String, propertyName: String) { + self.base = PropertyAccessExp(baseName: baseName, propertyName: propertyName) + } + + public var syntax: SyntaxProtocol { + let memberAccess = + base.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + return ExprSyntax( + PrefixOperatorExprSyntax( + operator: .prefixOperator("!", leadingTrivia: [], trailingTrivia: []), + expression: memberAccess + ) + ) + } +} + /// An expression that calls a function. public struct FunctionCallExp: CodeBlock { internal let baseName: String diff --git a/Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift b/Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift new file mode 100644 index 0000000..4c20266 --- /dev/null +++ b/Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift @@ -0,0 +1,84 @@ +// +// TokenVisitor+Helpers.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +extension TokenVisitor { + func processToken(_ token: TokenSyntax) { + var kind = "\(token.tokenKind)" + if let index = kind.firstIndex(of: "(") { + kind = String(kind.prefix(upTo: index)) + } + if kind.hasSuffix("Keyword") { + kind = "keyword" + } + + let sourceRange = token.sourceRange(converter: locationConverter) + let start = sourceRange.start + let end = sourceRange.end + let text = token.presence == .present || showMissingTokens ? token.text : "" + } + + func processTriviaPiece(_ piece: TriviaPiece) -> String { + func wrapWithSpanTag(class className: String, text: String) -> String { + "\(text.escapeHTML().replaceInvisiblesWithHTML())" + } + + var trivia = "" + switch piece { + case .spaces(let count): + trivia += String(repeating: " ", count: count) + case .tabs(let count): + trivia += String(repeating: " ", count: count * 2) + case .verticalTabs, .formfeeds: + break + case .newlines(let count), .carriageReturns(let count), .carriageReturnLineFeeds(let count): + trivia += String(repeating: "
", count: count) + case .lineComment(let text): + trivia += wrapWithSpanTag(class: "lineComment", text: text) + case .blockComment(let text): + trivia += wrapWithSpanTag(class: "blockComment", text: text) + case .docLineComment(let text): + trivia += wrapWithSpanTag(class: "docLineComment", text: text) + case .docBlockComment(let text): + trivia += wrapWithSpanTag(class: "docBlockComment", text: text) + case .unexpectedText(let text): + trivia += wrapWithSpanTag(class: "unexpectedText", text: text) + case .backslashes(let count): + trivia += String(repeating: #"\"#, count: count) + case .pounds(let count): + trivia += String(repeating: "#", count: count) + } + return trivia + } +} diff --git a/Sources/SyntaxKit/parser/TokenVisitor.swift b/Sources/SyntaxKit/parser/TokenVisitor.swift index 4eef1ff..09a8e3d 100644 --- a/Sources/SyntaxKit/parser/TokenVisitor.swift +++ b/Sources/SyntaxKit/parser/TokenVisitor.swift @@ -37,8 +37,8 @@ internal final class TokenVisitor: SyntaxRewriter { private var current: TreeNode! private var index = 0 - private let locationConverter: SourceLocationConverter - private let showMissingTokens: Bool + internal let locationConverter: SourceLocationConverter + internal let showMissingTokens: Bool internal init(locationConverter: SourceLocationConverter, showMissingTokens: Bool) { self.locationConverter = locationConverter @@ -206,55 +206,4 @@ internal final class TokenVisitor: SyntaxRewriter { current = nil } } - - private func processToken(_ token: TokenSyntax) { - var kind = "\(token.tokenKind)" - if let index = kind.firstIndex(of: "(") { - kind = String(kind.prefix(upTo: index)) - } - if kind.hasSuffix("Keyword") { - kind = "keyword" - } - - let sourceRange = token.sourceRange(converter: locationConverter) - let start = sourceRange.start - let end = sourceRange.end - let text = token.presence == .present || showMissingTokens ? token.text : "" - } - - private func processTriviaPiece(_ piece: TriviaPiece) -> String { - func wrapWithSpanTag(class className: String, text: String) -> String { - "\(text.escapeHTML().replaceInvisiblesWithHTML())" - } - - var trivia = "" - switch piece { - case .spaces(let count): - trivia += String(repeating: " ", count: count) - case .tabs(let count): - trivia += String(repeating: " ", count: count * 2) - case .verticalTabs, .formfeeds: - break - case .newlines(let count), .carriageReturns(let count), .carriageReturnLineFeeds(let count): - trivia += String(repeating: "
", count: count) - case .lineComment(let text): - trivia += wrapWithSpanTag(class: "lineComment", text: text) - case .blockComment(let text): - trivia += wrapWithSpanTag(class: "blockComment", text: text) - case .docLineComment(let text): - trivia += wrapWithSpanTag(class: "docLineComment", text: text) - case .docBlockComment(let text): - trivia += wrapWithSpanTag(class: "docBlockComment", text: text) - case .unexpectedText(let text): - trivia += wrapWithSpanTag(class: "unexpectedText", text: text) - case .backslashes(let count): - trivia += String(repeating: #"\"#, count: count) - case .pounds(let count): - trivia += String(repeating: "#", count: count) - } - return trivia - } } diff --git a/Tests/SyntaxKitTests/Integration/CommentTests.swift b/Tests/SyntaxKitTests/Integration/CommentTests.swift index 1cd2e8e..6397f11 100644 --- a/Tests/SyntaxKitTests/Integration/CommentTests.swift +++ b/Tests/SyntaxKitTests/Integration/CommentTests.swift @@ -21,7 +21,9 @@ internal struct CommentTests { Line(.doc, "Represents a playing card in a standard 52-card deck") Line(.doc) Line( - .doc, "A card has a rank (2-10, J, Q, K, A) and a suit (hearts, diamonds, clubs, spades)." + .doc, + "A card has a rank (2-10, J, Q, K, A) and a suit " + + "(hearts, diamonds, clubs, spades)." ) Line(.doc, "Each card can be compared to other cards based on its rank.") } @@ -102,7 +104,8 @@ internal struct CommentTests { #expect(!generated.isEmpty) // // #expect(generated.contains("MARK: - Models"), "MARK line should be present in generated code") - // #expect(generated.contains("Foo struct docs"), "Doc comment line should be present in generated code") + // #expect(generated.contains("Foo struct docs"), + // "Doc comment line should be present in generated code") // // Ensure the struct declaration itself is still correct // #expect(generated.contains("struct Foo")) // #expect(generated.contains("bar"), "Variable declaration should be present") diff --git a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift new file mode 100644 index 0000000..9aac57b --- /dev/null +++ b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift @@ -0,0 +1,157 @@ +import Foundation +import Testing + +@testable import SyntaxKit + +@Suite internal struct ConcurrencyExampleTests { + @Test("Concurrency vending machine DSL generates expected Swift code") + internal func testConcurrencyVendingMachineExample() throws { + // Build DSL equivalent of Examples/Remaining/concurrency/dsl.swift + // Note: This test includes the Item struct that's referenced but not defined in the original DSL + + let program = Group { + // Item struct (needed for the vending machine) + Struct("Item") { + Variable(.let, name: "price", type: "Int").withExplicitType() + Variable(.var, name: "count", type: "Int").withExplicitType() + } + + // VendingMachineError enum + Enum("VendingMachineError") { + Case("invalidSelection") + Case("insufficientFunds").associatedValue("coinsNeeded", type: "Int") + Case("outOfStock") + } + .inherits("Error") + + // VendingMachine class + Class("VendingMachine") { + Variable( + .var, name: "inventory", + equals: DictionaryExpr([ + ( + Literal.string("Candy Bar"), + Init("Item") { + ParameterExp(name: "price", value: Literal.integer(12)) + ParameterExp(name: "count", value: Literal.integer(7)) + } + ), + ( + Literal.string("Chips"), + Init("Item") { + ParameterExp(name: "price", value: Literal.integer(10)) + ParameterExp(name: "count", value: Literal.integer(4)) + } + ), + ( + Literal.string("Pretzels"), + Init("Item") { + ParameterExp(name: "price", value: Literal.integer(7)) + ParameterExp(name: "count", value: Literal.integer(11)) + } + ), + ]) + ) + Variable(.var, name: "coinsDeposited", equals: 0) + + Function("vend") { + Parameter("name", labeled: "itemNamed", type: "String") + } _: { + Guard { + Let("item", "inventory[name]") + } else: { + Throw(VariableExp("VendingMachineError.invalidSelection")) + } + Guard { + Infix(">") { + VariableExp("item").property("count") + Literal.integer(0) + } + } else: { + Throw(VariableExp("VendingMachineError.outOfStock")) + } + Guard { + Infix("<=") { + VariableExp("item").property("price") + VariableExp("coinsDeposited") + } + } else: { + Throw( + Call("VendingMachineError.insufficientFunds") { + ParameterExp( + name: "coinsNeeded", + value: Infix("-") { + VariableExp("item").property("price") + VariableExp("coinsDeposited") + } + ) + } + ) + } + Infix("-=") { + VariableExp("coinsDeposited") + VariableExp("item").property("price") + } + Variable(.var, name: "newItem", equals: Literal.ref("item")) + Infix("-=") { + VariableExp("newItem").property("count") + Literal.integer(1) + } + Assignment("inventory[name]", .ref("newItem")) + Call("print") { + ParameterExp(unlabeled: "\"Dispensing \\(name)\"") + } + } + .throws() + } + } + + // Expected Swift code from Examples/Remaining/concurrency/code.swift + let expectedCode = """ + struct Item { + let price: Int + var count: Int + } + + enum VendingMachineError: Error { + case invalidSelection + case insufficientFunds(coinsNeeded: Int) + case outOfStock + } + + class VendingMachine { + var inventory = ["Candy Bar": Item(price: 12, count: 7), + "Chips": Item(price: 10, count: 4), + "Pretzels": Item(price: 7, count: 11)] + var coinsDeposited = 0 + + func vend(itemNamed name: String) throws { + guard let item = inventory[name] else { + throw VendingMachineError.invalidSelection + } + + guard item.count > 0 else { + throw VendingMachineError.outOfStock + } + + guard item.price <= coinsDeposited else { + throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited) + } + + coinsDeposited -= item.price + + var newItem = item + newItem.count -= 1 + inventory[name] = newItem + + print("Dispensing \\(name)") + } + } + """ + + // Generate code from DSL + let generated = program.generateCode().normalize() + let expected = expectedCode.normalize() + #expect(generated == expected) + } +} diff --git a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift index 585c458..821c215 100644 --- a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift @@ -200,13 +200,15 @@ import Testing SwitchCase(Tuple.pattern([(-2...2), (-2...2)])) { Call("print") { ParameterExp( - name: "", value: "\"(\\(somePoint.0), \\(somePoint.1)) is inside the box\"") + name: "", value: "\"(\\(somePoint.0), \\(somePoint.1)) is inside the box\"" + ) } } Default { Call("print") { ParameterExp( - name: "", value: "\"(\\(somePoint.0), \\(somePoint.1)) is outside of the box\"") + name: "", value: "\"(\\(somePoint.0), \\(somePoint.1)) is outside of the box\"" + ) } } } @@ -220,17 +222,23 @@ import Testing Switch("anotherPoint") { SwitchCase(Tuple.pattern([Pattern.let("x"), 0])) { Call("print") { - ParameterExp(name: "", value: "\"on the x-axis with an x value of \\(x)\"") + ParameterExp( + name: "", value: "\"on the x-axis with an x value of \\(x)\"" + ) } } SwitchCase(Tuple.pattern([0, Pattern.let("y")])) { Call("print") { - ParameterExp(name: "", value: "\"on the y-axis with a y value of \\(y)\"") + ParameterExp( + name: "", value: "\"on the y-axis with a y value of \\(y)\"" + ) } } SwitchCase(Tuple.pattern([Pattern.let("x"), Pattern.let("y")])) { Call("print") { - ParameterExp(name: "", value: "\"somewhere else at (\\(x), \\(y))\"") + ParameterExp( + name: "", value: "\"somewhere else at (\\(x), \\(y))\"" + ) } } } @@ -269,7 +277,8 @@ import Testing value: Infix("+") { VariableExp("finalSquare") Literal.integer(1) - }) + } + ) } } diff --git a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift index ef823bb..3c8aabb 100644 --- a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift @@ -11,9 +11,12 @@ import Testing let program = Group { // MARK: - Basic For-in Loop Variable( - .let, name: "names", + .let, + name: "names", equals: Literal.array([ - Literal.string("Alice"), Literal.string("Bob"), Literal.string("Charlie"), + Literal.string("Alice"), + Literal.string("Bob"), + Literal.string("Charlie"), ]) ) .comment { @@ -22,12 +25,14 @@ import Testing } For( - VariableExp("name"), in: VariableExp("names"), + VariableExp("name"), + in: VariableExp("names"), then: { Call("print") { ParameterExp(unlabeled: "\"Hello, \\(name)!\"") } - }) + } + ) // MARK: - For-in with Enumerated Call("print") { @@ -38,13 +43,17 @@ import Testing Line("For-in loop with enumerated() to get index and value") } For( - Tuple.patternCodeBlock([VariableExp("index"), VariableExp("name")]), + Tuple.patternCodeBlock([ + VariableExp("index"), + VariableExp("name"), + ]), in: VariableExp("names").call("enumerated"), then: { Call("print") { ParameterExp(unlabeled: "\"Index: \\(index), Name: \\(name)\"") } - }) + } + ) // MARK: - For-in with Where Clause Call("print") { @@ -55,15 +64,25 @@ import Testing Line("For-in loop with where clause") } Variable( - .let, name: "numbers", + .let, + name: "numbers", equals: Literal.array([ - Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), - Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), - Literal.integer(9), Literal.integer(10), - ])) + Literal.integer(1), + Literal.integer(2), + Literal.integer(3), + Literal.integer(4), + Literal.integer(5), + Literal.integer(6), + Literal.integer(7), + Literal.integer(8), + Literal.integer(9), + Literal.integer(10), + ]) + ) For( - VariableExp("number"), in: VariableExp("numbers"), + VariableExp("number"), + in: VariableExp("numbers"), where: { Infix("==") { Infix("%") { @@ -89,21 +108,27 @@ import Testing Line("For-in loop over dictionary") } Variable( - .let, name: "scores", + .let, + name: "scores", equals: Literal.dictionary([ (Literal.string("Alice"), Literal.integer(95)), (Literal.string("Bob"), Literal.integer(87)), (Literal.string("Charlie"), Literal.integer(92)), - ])) + ]) + ) For( - Tuple.patternCodeBlock([VariableExp("name"), VariableExp("score")]), + Tuple.patternCodeBlock([ + VariableExp("name"), + VariableExp("score"), + ]), in: VariableExp("scores"), then: { Call("print") { ParameterExp(unlabeled: "\"\\(name): \\(score)\"") } - }) + } + ) } // Generate Swift from DSL diff --git a/Tests/SyntaxKitTests/Unit/AttributeTests.swift b/Tests/SyntaxKitTests/Unit/AttributeTests.swift index 3c70141..e71f4ee 100644 --- a/Tests/SyntaxKitTests/Unit/AttributeTests.swift +++ b/Tests/SyntaxKitTests/Unit/AttributeTests.swift @@ -176,7 +176,7 @@ import Testing let generated = function.syntax.description #expect(generated.contains("@escaping")) - #expect(generated.contains("data: Data")) + #expect(generated.contains("data : Data")) #expect(generated.contains("func process")) } @@ -193,7 +193,7 @@ import Testing #expect(generated.contains("@available")) #expect(generated.contains("iOS")) #expect(generated.contains("17.0")) - #expect(generated.contains("input: String")) + #expect(generated.contains("input : String")) #expect(generated.contains("func validate")) } } diff --git a/Tests/SyntaxKitTests/Unit/CatchBasicTests.swift b/Tests/SyntaxKitTests/Unit/CatchBasicTests.swift new file mode 100644 index 0000000..dcaad97 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/CatchBasicTests.swift @@ -0,0 +1,157 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct CatchBasicTests { + // MARK: - Basic Catch Tests + + @Test("Basic catch without pattern generates correct syntax") + internal func testBasicCatchWithoutPattern() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("An error occurred")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch { print(\"An error occurred\") } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with enum case pattern generates correct syntax") + internal func testCatchWithEnumCasePattern() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("connectionFailed")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Connection failed")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .connectionFailed { print(\"Connection failed\") } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with enum case and associated value generates correct syntax") + internal func testCatchWithEnumCaseAndAssociatedValue() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("invalidInput").associatedValue("fieldName", type: "String")) { + Call("print") { + ParameterExp( + unlabeled: Literal.string("Invalid input for field: \\(fieldName)") + ) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .invalidInput(let fieldName) { print(\"Invalid input for field: \\(fieldName)\") } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + // MARK: - Catch with Different Pattern Types + + @Test("Catch with multiple enum cases generates correct syntax") + internal func testCatchWithMultipleEnumCases() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("timeout")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Request timed out")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .timeout { print(\"Request timed out\") } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with error binding generates correct syntax") + internal func testCatchWithErrorBinding() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch { + Call("logError") { + ParameterExp(name: "error", value: VariableExp("error")) + } + Call("print") { + ParameterExp( + unlabeled: Literal.string("Error: \\(error)") + ) + } + } + } + + let generated = doCatch.generateCode() + let expected = + "do { try someFunction(param: \"test\") } catch { logError(error: error) print(\"Error: \\(error)\") }" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with specific error type generates correct syntax") + internal func testCatchWithSpecificErrorType() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("CustomError")) { + Call("handleCustomError") { + ParameterExp(name: "error", value: VariableExp("error")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .CustomError { handleCustomError(error: error) } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/CatchComplexTests.swift b/Tests/SyntaxKitTests/Unit/CatchComplexTests.swift new file mode 100644 index 0000000..5fbb362 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/CatchComplexTests.swift @@ -0,0 +1,110 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct CatchComplexTests { + // MARK: - Complex Catch Patterns + + @Test("Catch with multiple associated values generates correct syntax") + internal func testCatchWithMultipleAssociatedValues() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch( + EnumCase("requestFailed") + .associatedValue("statusCode", type: "Int") + .associatedValue("message", type: "String") + ) { + Call("logAPIError") { + ParameterExp(name: "statusCode", value: VariableExp("statusCode")) + ParameterExp(name: "message", value: VariableExp("message")) + } + } + } + + let generated = doCatch.generateCode() + let expected = + "do { try someFunction(param: \"test\") } catch .requestFailed(let statusCode, let message) { " + + "logAPIError(statusCode: statusCode, message: message) }" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with where clause generates correct syntax") + internal func testCatchWithWhereClause() throws { + // Note: This would require additional DSL support for where clauses + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("connectionFailed")) { + Call("retryConnection") { + ParameterExp(name: "maxAttempts", value: Literal.integer(3)) + } + } + } + + let generated = doCatch.generateCode() + let expected = + "do { try someFunction(param: \"test\") } catch .connectionFailed { retryConnection(maxAttempts: 3) }" + + #expect(generated.normalize() == expected.normalize()) + } + + // MARK: - Catch with Complex Body + + @Test("Catch with multiple statements generates correct syntax") + internal func testCatchWithMultipleStatements() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("invalidEmail")) { + Call("logValidationError") { + ParameterExp(name: "field", value: Literal.string("email")) + } + Variable(.let, name: "errorMessage", equals: Literal.string("Invalid email format")) + Call("showError") { + ParameterExp(name: "message", value: VariableExp("errorMessage")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { try someFunction(param: "test") } catch .invalidEmail { logValidationError(field: "email") let errorMessage = "Invalid email format" showError(message: errorMessage) } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with nested control flow generates correct syntax") + internal func testCatchWithNestedControlFlow() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("connectionFailed")) { + Variable(.let, name: "retryCount", equals: Literal.integer(0)) + Call("attemptConnection") { + ParameterExp(name: "attempt", value: VariableExp("retryCount")) + } + Call("incrementRetryCount") { + ParameterExp(name: "current", value: VariableExp("retryCount")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { try someFunction(param: "test") } catch .connectionFailed { let retryCount = 0 attemptConnection(attempt: retryCount) incrementRetryCount(current: retryCount) } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/CatchEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/CatchEdgeCaseTests.swift new file mode 100644 index 0000000..861f339 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/CatchEdgeCaseTests.swift @@ -0,0 +1,113 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct CatchEdgeCaseTests { + // MARK: - Edge Cases + + @Test("Catch with empty body generates correct syntax") + internal func testCatchWithEmptyBody() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("ignored")) { + // Empty body + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .ignored { } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with single statement generates correct syntax") + internal func testCatchWithSingleStatement() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("connectionFailed")) { + Call("retry") { + ParameterExp(name: "maxAttempts", value: Literal.integer(1)) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .connectionFailed { retry(maxAttempts: 1) } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with function call and variable assignment generates correct syntax") + internal func testCatchWithFunctionCallAndVariableAssignment() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("invalidInput")) { + Variable(.let, name: "errorMessage", equals: Literal.string("Invalid input")) + Call("logError") { + ParameterExp(name: "message", value: VariableExp("errorMessage")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .invalidInput { + let errorMessage = "Invalid input" + logError(message: errorMessage) + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with conditional logic generates correct syntax") + internal func testCatchWithConditionalLogic() throws { + let doCatch = Do { + Call("someFunction") { + ParameterExp(name: "param", value: Literal.string("test")) + }.throwing() + } catch: { + Catch(EnumCase("connectionFailed")) { + Variable(.let, name: "retryCount", equals: Literal.integer(0)) + Call("checkRetryCount") { + ParameterExp(name: "count", value: VariableExp("retryCount")) + } + Call("showError") { + ParameterExp(name: "message", value: Literal.string("Max retries exceeded")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try someFunction(param: "test") + } catch .connectionFailed { + let retryCount = 0 + checkRetryCount(count: retryCount) + showError(message: "Max retries exceeded") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/CatchIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/CatchIntegrationTests.swift new file mode 100644 index 0000000..0fd1c4e --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/CatchIntegrationTests.swift @@ -0,0 +1,124 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct CatchIntegrationTests { + // MARK: - Integration Tests + + @Test("Catch in do-catch statement generates correct syntax") + internal func testCatchInDoCatchStatement() throws { + let doCatch = Do { + Call("fetchData") { + ParameterExp(name: "id", value: Literal.integer(123)) + }.throwing() + } catch: { + Catch(EnumCase("connectionFailed")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Connection failed")) + } + } + Catch(EnumCase("invalidId")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Invalid ID")) + } + } + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Unexpected error: \\(error)")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try fetchData(id: 123) + } catch .connectionFailed { + print("Connection failed") + } catch .invalidId { + print("Invalid ID") + } catch { + print("Unexpected error: \\(error)") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with async operations generates correct syntax") + internal func testCatchWithAsyncOperations() throws { + let doCatch = Do { + Variable(.let, name: "data") { + Call("fetchData") { + ParameterExp(name: "id", value: Literal.integer(123)) + } + }.async() + } catch: { + Catch(EnumCase("timeout")) { + Variable(.let, name: "fallbackData") { + Call("fetchFallbackData") { + ParameterExp(name: "id", value: Literal.integer(123)) + } + }.async() + } + Catch { + Call("logError") { + ParameterExp(name: "error", value: VariableExp("error")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + async let data = fetchData(id: 123) + } catch .timeout { + async let fallbackData = fetchFallbackData(id: 123) + } catch { + logError(error: error) + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Catch with error recovery generates correct syntax") + internal func testCatchWithErrorRecovery() throws { + let doCatch = Do { + Call("processUserData") { + ParameterExp(name: "user", value: VariableExp("user")) + }.throwing() + } catch: { + Catch( + EnumCase("missingField") + .associatedValue("fieldName", type: "String") + ) { + Call("setDefaultValue") { + ParameterExp(name: "field", value: VariableExp("fieldName")) + } + Call("processUserData") { + ParameterExp(name: "user", value: VariableExp("user")) + }.throwing() + } + Catch { + Call("handleUnexpectedError") { + ParameterExp(name: "error", value: VariableExp("error")) + } + } + } + + let generated = doCatch.generateCode() + let expected = """ + do { + try processUserData(user: user) + } catch .missingField(let fieldName) { + setDefaultValue(field: fieldName) + try processUserData(user: user) + } catch { + handleUnexpectedError(error: error) + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift b/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift index ab867ee..9591a6e 100644 --- a/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift @@ -41,7 +41,8 @@ internal struct CodeStyleMigrationTests { // Verify proper indentation is maintained #expect( generated - == "struct IndentationTest { let property1: String let property2: Int func method(param: String) { let local = \"value\" return local } }" + == "struct IndentationTest { let property1: String let property2: Int " + + "func method(param: String) { let local = \"value\" return local } }" ) } diff --git a/Tests/SyntaxKitTests/Unit/DoBasicTests.swift b/Tests/SyntaxKitTests/Unit/DoBasicTests.swift new file mode 100644 index 0000000..7ca7cf7 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/DoBasicTests.swift @@ -0,0 +1,91 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct DoBasicTests { + // MARK: - Basic Do Tests + + @Test("Basic do statement generates correct syntax") + internal func testBasicDoStatement() throws { + let doStatement = Do { + Call("print") { + ParameterExp(unlabeled: Literal.string("Hello, World!")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error occurred")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + print("Hello, World!") + } catch { + print("Error occurred") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with multiple statements generates correct syntax") + internal func testDoStatementWithMultipleStatements() throws { + let doStatement = Do { + Variable(.let, name: "message", equals: Literal.string("Hello")) + Call("print") { + ParameterExp(unlabeled: VariableExp("message")) + } + Call("logMessage") { + ParameterExp(name: "text", value: VariableExp("message")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error occurred")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + let message = "Hello" + print(message) + logMessage(text: message) + } catch { + print("Error occurred") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with throwing function generates correct syntax") + internal func testDoStatementWithThrowingFunction() throws { + let doStatement = Do { + Call("fetchData") { + ParameterExp(name: "id", value: Literal.integer(123)) + }.throwing() + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Failed to fetch data")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + try fetchData(id: 123) + } catch { + print("Failed to fetch data") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/DoComplexTests.swift b/Tests/SyntaxKitTests/Unit/DoComplexTests.swift new file mode 100644 index 0000000..955b7e4 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/DoComplexTests.swift @@ -0,0 +1,112 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct DoComplexTests { + // MARK: - Do with Complex Body + + @Test("Do statement with variable declarations generates correct syntax") + internal func testDoStatementWithVariableDeclarations() throws { + let doStatement = Do { + Variable(.let, name: "user", equals: Literal.string("John")) + Variable(.let, name: "age", equals: Literal.integer(30)) + Variable(.let, name: "isActive", equals: Literal.boolean(true)) + Call("processUser") { + ParameterExp(name: "name", value: VariableExp("user")) + ParameterExp(name: "age", value: VariableExp("age")) + ParameterExp(name: "active", value: VariableExp("isActive")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error processing user")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + let user = "John" + let age = 30 + let isActive = true + processUser(name: user, age: age, active: isActive) + } catch { + print("Error processing user") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with async operations generates correct syntax") + internal func testDoStatementWithAsyncOperations() throws { + let doStatement = Do { + Variable(.let, name: "data") { + Call("fetchData") { + ParameterExp(name: "id", value: Literal.integer(123)) + } + }.async() + Variable(.let, name: "posts") { + Call("fetchPosts") { + ParameterExp(name: "userId", value: Literal.integer(123)) + } + }.async() + Call("processResults") { + ParameterExp(name: "data", value: VariableExp("data")) + ParameterExp(name: "posts", value: VariableExp("posts")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error in async operations")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + async let data = fetchData(id: 123) + async let posts = fetchPosts(userId: 123) + processResults(data: data, posts: posts) + } catch { + print("Error in async operations") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with control flow generates correct syntax") + internal func testDoStatementWithControlFlow() throws { + let doStatement = Do { + Variable(.let, name: "count", equals: Literal.integer(5)) + Call("checkCount") { + ParameterExp(name: "value", value: VariableExp("count")) + } + Call("print") { + ParameterExp(unlabeled: Literal.string("Count processed")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error in control flow")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + let count = 5 + checkCount(value: count) + print("Count processed") + } catch { + print("Error in control flow") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/DoEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/DoEdgeCaseTests.swift new file mode 100644 index 0000000..7bc1147 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/DoEdgeCaseTests.swift @@ -0,0 +1,156 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct DoEdgeCaseTests { + // MARK: - Edge Cases + + @Test("Do statement with empty body generates correct syntax") + internal func testDoStatementWithEmptyBody() throws { + let doStatement = Do { + // Empty body + } catch: { + Catch { + // Empty catch + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + } catch { + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with single expression generates correct syntax") + internal func testDoStatementWithSingleExpression() throws { + let doStatement = Do { + VariableExp("someVariable") + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + someVariable + } catch { + print("Error") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with function call and variable assignment generates correct syntax") + internal func testDoStatementWithFunctionCallAndVariableAssignment() throws { + let doStatement = Do { + Variable(.let, name: "result", equals: Literal.integer(42)) + Call("processResult") { + ParameterExp(name: "value", value: VariableExp("result")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error processing result")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + let result = 42 + processResult(value: result) + } catch { + print("Error processing result") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with nested do statement generates correct syntax") + internal func testDoStatementWithNestedDoStatement() throws { + let doStatement = Do { + Call("outerFunction") { + ParameterExp(name: "param", value: Literal.string("outer")) + } + Do { + Call("innerFunction") { + ParameterExp(name: "param", value: Literal.string("inner")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Inner error")) + } + } + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Outer error")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + outerFunction(param: "outer") + do { + innerFunction(param: "inner") + } catch { + print("Inner error") + } + } catch { + print("Outer error") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with tuple assignment generates correct syntax") + internal func testDoStatementWithTupleAssignment() throws { + let doStatement = Do { + TupleAssignment( + ["x", "y"], + equals: Tuple { + Literal.integer(10) + Literal.integer(20) + } + ) + Call("processCoordinates") { + ParameterExp(name: "x", value: VariableExp("x")) + ParameterExp(name: "y", value: VariableExp("y")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Error processing coordinates")) + } + } + } + + let generated = doStatement.generateCode() + let expected = """ + do { + let (x, y) = (10, 20) + processCoordinates(x: x, y: y) + } catch { + print("Error processing coordinates") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/DoIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/DoIntegrationTests.swift new file mode 100644 index 0000000..d5cb69d --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/DoIntegrationTests.swift @@ -0,0 +1,88 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct DoIntegrationTests { + // MARK: - Integration Tests + + @Test("Do statement in function generates correct syntax") + internal func testDoStatementInFunction() throws { + let function = Function("processData") { + Parameter(name: "input", type: "[Int]") + } _: { + Do { + Call("validateInput") { + ParameterExp(name: "data", value: VariableExp("input")) + }.throwing() + Call("processValidData") { + ParameterExp(name: "data", value: VariableExp("input")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Validation failed")) + } + } + } + } + + let generated = function.generateCode() + let expected = """ + func processData(input: [Int]) { + do { + try validateInput(data: input) + processValidData(data: input) + } catch { + print("Validation failed") + } + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Do statement with async function generates correct syntax") + internal func testDoStatementWithAsyncFunction() throws { + let function = Function("fetchUserData") { + Parameter(name: "userId", type: "Int") + } _: { + Do { + Variable(.let, name: "user") { + Call("fetchUser") { + ParameterExp(name: "id", value: VariableExp("userId")) + } + }.async() + Variable(.let, name: "profile") { + Call("fetchProfile") { + ParameterExp(name: "userId", value: VariableExp("userId")) + } + }.async() + Call("combineUserData") { + ParameterExp(name: "user", value: VariableExp("user")) + ParameterExp(name: "profile", value: VariableExp("profile")) + } + } catch: { + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Failed to fetch user data")) + } + } + } + }.async() + + let generated = function.generateCode() + let expected = """ + func fetchUserData(userId: Int) async { + do { + async let user = fetchUser(id: userId) + async let profile = fetchProfile(userId: userId) + combineUserData(user: user, profile: profile) + } catch { + print("Failed to fetch user data") + } + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift index 55c7c96..c4a5720 100644 --- a/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift +++ b/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift @@ -32,257 +32,4 @@ internal struct EdgeCaseTests { // This test documents the expected behavior #expect(true) // Placeholder - fatal errors can't be easily tested } - - // MARK: - Switch and Case Tests - - @Test("Switch with multiple patterns generates correct syntax") - internal func testSwitchWithMultiplePatterns() throws { - let switchStmt = Switch("value") { - SwitchCase("1") { - Return { VariableExp("one") } - } - SwitchCase("2") { - Return { VariableExp("two") } - } - } - - let generated = switchStmt.generateCode() - #expect(generated.contains("switch value")) - #expect(generated.contains("case 1:")) - #expect(generated.contains("case 2:")) - } - - @Test("SwitchCase with multiple patterns generates correct syntax") - internal func testSwitchCaseWithMultiplePatterns() throws { - let switchCase = SwitchCase("1", "2", "3") { - Return { VariableExp("number") } - } - - let generated = switchCase.generateCode() - #expect(generated.contains("case 1, 2, 3:")) - } - - // MARK: - Complex Expression Tests - - @Test("Infix with complex expressions generates correct syntax") - internal func testInfixWithComplexExpressions() throws { - let infix = Infix("*") { - Parenthesized { - Infix("+") { - VariableExp("a") - VariableExp("b") - } - } - Parenthesized { - Infix("-") { - VariableExp("c") - VariableExp("d") - } - } - } - - let generated = infix.generateCode() - #expect(generated.contains("(a + b) * (c - d)")) - } - - @Test("Return with VariableExp generates correct syntax") - internal func testReturnWithVariableExp() throws { - let returnStmt = Return { - VariableExp("result") - } - - let generated = returnStmt.generateCode() - #expect(generated.contains("return result")) - } - - @Test("Return with complex expression generates correct syntax") - internal func testReturnWithComplexExpression() throws { - let returnStmt = Return { - Infix("+") { - VariableExp("a") - VariableExp("b") - } - } - - let generated = returnStmt.generateCode() - #expect(generated.contains("return a + b")) - } - - // MARK: - CodeBlock Expression Tests - - @Test("CodeBlock expr with TokenSyntax wraps in DeclReferenceExpr") - internal func testCodeBlockExprWithTokenSyntax() throws { - let variableExp = VariableExp("x") - let expr = variableExp.expr - - let generated = expr.description - #expect(generated.contains("x")) - } - - // MARK: - Code Generation Edge Cases - - @Test("CodeBlock generateCode with CodeBlockItemListSyntax") - internal func testCodeBlockGenerateCodeWithItemList() throws { - let group = Group { - Variable(.let, name: "x", type: "Int", equals: 1).withExplicitType() - Variable(.let, name: "y", type: "Int", equals: 2).withExplicitType() - } - - let generated = group.generateCode() - #expect(generated.contains("let x : Int = 1")) - #expect(generated.contains("let y : Int = 2")) - } - - @Test("CodeBlock generateCode with single declaration") - internal func testCodeBlockGenerateCodeWithSingleDeclaration() throws { - let variable = Variable(.let, name: "x", type: "Int", equals: 1).withExplicitType() - - let generated = variable.generateCode() - #expect(generated.contains("let x : Int = 1")) - } - - @Test("CodeBlock generateCode with single statement") - internal func testCodeBlockGenerateCodeWithSingleStatement() throws { - let assignment = Assignment("x", Literal.integer(42)) - - let generated = assignment.generateCode() - #expect(generated.contains("x = 42")) - } - - @Test("CodeBlock generateCode with single expression") - internal func testCodeBlockGenerateCodeWithSingleExpression() throws { - let variableExp = VariableExp("x") - - let generated = variableExp.generateCode() - #expect(generated.contains("x")) - } - - // MARK: - Complex Type Tests - - @Test("TypeAlias with complex nested types") - internal func testTypeAliasWithComplexNestedTypes() throws { - let typeAlias = TypeAlias("ComplexType", equals: "Array>>") - - let generated = typeAlias.generateCode() - #expect( - generated.normalize().contains( - "typealias ComplexType = Array>>".normalize())) - } - - @Test("TypeAlias with multiple generic parameters") - internal func testTypeAliasWithMultipleGenericParameters() throws { - let typeAlias = TypeAlias("Result", equals: "Result") - - let generated = typeAlias.generateCode().normalize() - #expect(generated.contains("typealias Result = Result".normalize())) - } - - // MARK: - Function Parameter Tests - - @Test("Function with unnamed parameter generates correct syntax") - internal func testFunctionWithUnnamedParameter() throws { - let function = Function("process") { - Parameter(name: "data", type: "Data", isUnnamed: true) - } _: { - Variable(.let, name: "result", type: "String", equals: "processed") - } - - let generated = function.generateCode() - #expect(generated.contains("func process(_ data: Data)")) - } - - @Test("Function with parameter default value generates correct syntax") - internal func testFunctionWithParameterDefaultValue() throws { - let function = Function("greet") { - Parameter(name: "name", type: "String", defaultValue: "\"World\"") - } _: { - Variable(.let, name: "message", type: "String", equals: "greeting") - } - - let generated = function.generateCode() - #expect(generated.contains("func greet(name: String = \"World\")")) - } - - // MARK: - Enum Case Tests - - @Test("EnumCase with string raw value generates correct syntax") - internal func testEnumCaseWithStringRawValue() throws { - let enumDecl = Enum("Status") { - EnumCase("active").equals(Literal.string("active")) - EnumCase("inactive").equals(Literal.string("inactive")) - } - - let generated = enumDecl.generateCode().normalize() - #expect(generated.contains("case active = \"active\"")) - #expect(generated.contains("case inactive = \"inactive\"")) - } - - @Test("EnumCase with double raw value generates correct syntax") - internal func testEnumCaseWithDoubleRawValue() throws { - let enumDecl = Enum("Precision") { - EnumCase("low").equals(Literal.float(0.1)) - EnumCase("high").equals(Literal.float(0.001)) - } - - let generated = enumDecl.generateCode().normalize() - #expect(generated.contains("case low = 0.1")) - #expect(generated.contains("case high = 0.001")) - } - - // MARK: - Computed Property Tests - - @Test("ComputedProperty with complex return expression") - internal func testComputedPropertyWithComplexReturn() throws { - let computedProperty = ComputedProperty("description", type: "String") { - Return { - VariableExp("name").call("appending") { - ParameterExp(name: "", value: "\" - \" + String(count)") - } - } - } - - let generated = computedProperty.generateCode().normalize() - #expect(generated.contains("var description: String")) - #expect(generated.contains("return name.appending(\" - \" + String(count))")) - } - - // MARK: - Comment Integration Tests - - @Test("ComputedProperty with comments generates correct syntax") - internal func testComputedPropertyWithComments() throws { - let computedProperty = ComputedProperty("formattedName", type: "String") { - Return { - VariableExp("name").property("uppercased") - } - }.comment { - Line(.doc, "Returns the name in uppercase format") - } - - let generated = computedProperty.generateCode() - #expect(generated.contains("/// Returns the name in uppercase format")) - #expect(generated.contains("var formattedName : String")) - } - - // MARK: - Literal Tests - - @Test("Literal with nil generates correct syntax") - internal func testLiteralWithNil() throws { - let literal = Literal.nil - let generated = literal.generateCode() - #expect(generated.contains("nil")) - } - - @Test("Literal with boolean generates correct syntax") - internal func testLiteralWithBoolean() throws { - let literal = Literal.boolean(true) - let generated = literal.generateCode() - #expect(generated.contains("true")) - } - - @Test("Literal with float generates correct syntax") - internal func testLiteralWithFloat() throws { - let literal = Literal.float(3.14159) - let generated = literal.generateCode() - #expect(generated.contains("3.14159")) - } } diff --git a/Tests/SyntaxKitTests/Unit/EdgeCaseTestsExpressions.swift b/Tests/SyntaxKitTests/Unit/EdgeCaseTestsExpressions.swift new file mode 100644 index 0000000..8296755 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/EdgeCaseTestsExpressions.swift @@ -0,0 +1,129 @@ +import Testing + +@testable import SyntaxKit + +internal struct EdgeCaseTestsExpressions { + // MARK: - Switch and Case Tests + + @Test("Switch with multiple patterns generates correct syntax") + internal func testSwitchWithMultiplePatterns() throws { + let switchStmt = Switch("value") { + SwitchCase("1") { + Return { VariableExp("one") } + } + SwitchCase("2") { + Return { VariableExp("two") } + } + } + + let generated = switchStmt.generateCode() + #expect(generated.contains("switch value")) + #expect(generated.contains("case 1:")) + #expect(generated.contains("case 2:")) + } + + @Test("SwitchCase with multiple patterns generates correct syntax") + internal func testSwitchCaseWithMultiplePatterns() throws { + let switchCase = SwitchCase("1", "2", "3") { + Return { VariableExp("number") } + } + + let generated = switchCase.generateCode() + #expect(generated.contains("case 1, 2, 3:")) + } + + // MARK: - Complex Expression Tests + + @Test("Infix with complex expressions generates correct syntax") + internal func testInfixWithComplexExpressions() throws { + let infix = Infix("*") { + Parenthesized { + Infix("+") { + VariableExp("a") + VariableExp("b") + } + } + Parenthesized { + Infix("-") { + VariableExp("c") + VariableExp("d") + } + } + } + + let generated = infix.generateCode() + #expect(generated.contains("(a + b) * (c - d)")) + } + + @Test("Return with VariableExp generates correct syntax") + internal func testReturnWithVariableExp() throws { + let returnStmt = Return { + VariableExp("result") + } + + let generated = returnStmt.generateCode() + #expect(generated.contains("return result")) + } + + @Test("Return with complex expression generates correct syntax") + internal func testReturnWithComplexExpression() throws { + let returnStmt = Return { + Infix("+") { + VariableExp("a") + VariableExp("b") + } + } + + let generated = returnStmt.generateCode() + #expect(generated.contains("return a + b")) + } + + // MARK: - CodeBlock Expression Tests + + @Test("CodeBlock expr with TokenSyntax wraps in DeclReferenceExpr") + internal func testCodeBlockExprWithTokenSyntax() throws { + let variableExp = VariableExp("x") + let expr = variableExp.expr + + let generated = expr.description + #expect(generated.contains("x")) + } + + // MARK: - Code Generation Edge Cases + + @Test("CodeBlock generateCode with CodeBlockItemListSyntax") + internal func testCodeBlockGenerateCodeWithItemList() throws { + let group = Group { + Variable(.let, name: "x", type: "Int", equals: 1).withExplicitType() + Variable(.let, name: "y", type: "Int", equals: 2).withExplicitType() + } + + let generated = group.generateCode() + #expect(generated.contains("let x : Int = 1")) + #expect(generated.contains("let y : Int = 2")) + } + + @Test("CodeBlock generateCode with single declaration") + internal func testCodeBlockGenerateCodeWithSingleDeclaration() throws { + let variable = Variable(.let, name: "x", type: "Int", equals: 1).withExplicitType() + + let generated = variable.generateCode() + #expect(generated.contains("let x : Int = 1")) + } + + @Test("CodeBlock generateCode with single statement") + internal func testCodeBlockGenerateCodeWithSingleStatement() throws { + let assignment = Assignment("x", Literal.integer(42)) + + let generated = assignment.generateCode() + #expect(generated.contains("x = 42")) + } + + @Test("CodeBlock generateCode with single expression") + internal func testCodeBlockGenerateCodeWithSingleExpression() throws { + let variableExp = VariableExp("x") + + let generated = variableExp.generateCode() + #expect(generated.contains("x")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/EdgeCaseTestsTypes.swift b/Tests/SyntaxKitTests/Unit/EdgeCaseTestsTypes.swift new file mode 100644 index 0000000..237aa60 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/EdgeCaseTestsTypes.swift @@ -0,0 +1,136 @@ +import Testing + +@testable import SyntaxKit + +internal struct EdgeCaseTestsTypes { + // MARK: - Complex Type Tests + + @Test("TypeAlias with complex nested types") + internal func testTypeAliasWithComplexNestedTypes() throws { + let typeAlias = TypeAlias("ComplexType", equals: "Array>>") + + let generated = typeAlias.generateCode() + #expect( + generated.normalize().contains( + "typealias ComplexType = Array>>".normalize() + ) + ) + } + + @Test("TypeAlias with multiple generic parameters") + internal func testTypeAliasWithMultipleGenericParameters() throws { + let typeAlias = TypeAlias("Result", equals: "Result") + + let generated = typeAlias.generateCode().normalize() + #expect(generated.contains("typealias Result = Result".normalize())) + } + + // MARK: - Function Parameter Tests + + @Test("Function with unnamed parameter generates correct syntax") + internal func testFunctionWithUnnamedParameter() throws { + let function = Function("process") { + Parameter(name: "data", type: "Data", isUnnamed: true) + } _: { + Variable(.let, name: "result", type: "String", equals: "processed") + } + + let generated = function.generateCode() + #expect(generated.contains("func process(_ data: Data)")) + } + + @Test("Function with parameter default value generates correct syntax") + internal func testFunctionWithParameterDefaultValue() throws { + let function = Function("greet") { + Parameter(name: "name", type: "String", defaultValue: "\"World\"") + } _: { + Variable(.let, name: "message", type: "String", equals: "greeting") + } + + let generated = function.generateCode() + #expect(generated.contains("func greet(name : String = \"World\")")) + } + + // MARK: - Enum Case Tests + + @Test("EnumCase with string raw value generates correct syntax") + internal func testEnumCaseWithStringRawValue() throws { + let enumDecl = Enum("Status") { + EnumCase("active").equals(Literal.string("active")) + EnumCase("inactive").equals(Literal.string("inactive")) + } + + let generated = enumDecl.generateCode().normalize() + #expect(generated.contains("case active = \"active\"")) + #expect(generated.contains("case inactive = \"inactive\"")) + } + + @Test("EnumCase with double raw value generates correct syntax") + internal func testEnumCaseWithDoubleRawValue() throws { + let enumDecl = Enum("Precision") { + EnumCase("low").equals(Literal.float(0.1)) + EnumCase("high").equals(Literal.float(0.001)) + } + + let generated = enumDecl.generateCode().normalize() + #expect(generated.contains("case low = 0.1")) + #expect(generated.contains("case high = 0.001")) + } + + // MARK: - Computed Property Tests + + @Test("ComputedProperty with complex return expression") + internal func testComputedPropertyWithComplexReturn() throws { + let computedProperty = ComputedProperty("description", type: "String") { + Return { + VariableExp("name").call("appending") { + ParameterExp(name: "", value: "\" - \" + String(count)") + } + } + } + + let generated = computedProperty.generateCode().normalize() + #expect(generated.contains("var description: String")) + #expect(generated.contains("return name.appending(\" - \" + String(count))")) + } + + // MARK: - Comment Integration Tests + + @Test("ComputedProperty with comments generates correct syntax") + internal func testComputedPropertyWithComments() throws { + let computedProperty = ComputedProperty("formattedName", type: "String") { + Return { + VariableExp("name").property("uppercased") + } + }.comment { + Line(.doc, "Returns the name in uppercase format") + } + + let generated = computedProperty.generateCode() + #expect(generated.contains("/// Returns the name in uppercase format")) + #expect(generated.contains("var formattedName : String")) + } + + // MARK: - Literal Tests + + @Test("Literal with nil generates correct syntax") + internal func testLiteralWithNil() throws { + let literal = Literal.nil + let generated = literal.generateCode() + #expect(generated.contains("nil")) + } + + @Test("Literal with boolean generates correct syntax") + internal func testLiteralWithBoolean() throws { + let literal = Literal.boolean(true) + let generated = literal.generateCode() + #expect(generated.contains("true")) + } + + @Test("Literal with float generates correct syntax") + internal func testLiteralWithFloat() throws { + let literal = Literal.float(3.14159) + let generated = literal.generateCode() + #expect(generated.contains("3.14159")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift new file mode 100644 index 0000000..e68a119 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift @@ -0,0 +1,129 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct ErrorHandlingTests { + @Test("Error handling DSL generates expected Swift code") + internal func testErrorHandlingExample() throws { + let errorHandlingExample = Group { + Variable(.var, name: "vendingMachine", equals: Init("VendingMachine")) + Assignment("vendingMachine.coinsDeposited", Literal.integer(8)) + Do { + Call("buyFavoriteSnack") { + ParameterExp(name: "person", value: Literal.string("Alice")) + ParameterExp(name: "vendingMachine", value: Literal.ref("vendingMachine")) + }.throwing() + Call("print") { + ParameterExp(unlabeled: Literal.string("Success! Yum.")) + } + } catch: { + Catch(EnumCase("invalidSelection")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Invalid Selection.")) + } + } + Catch(EnumCase("outOfStock")) { + Call("print") { + ParameterExp(unlabeled: Literal.string("Out of Stock.")) + } + } + Catch( + EnumCase("insufficientFunds") + .associatedValue("coinsNeeded", type: "Int") + ) { + Call("print") { + ParameterExp( + unlabeled: Literal.string( + "Insufficient funds. Please insert an additional \\(coinsNeeded) coins." + ) + ) + } + } + Catch { + Call("print") { + ParameterExp(unlabeled: Literal.string("Unexpected error: \\(error).")) + } + } + } + } + + let generated = errorHandlingExample.generateCode() + let expected = """ + var vendingMachine = VendingMachine() + vendingMachine.coinsDeposited = 8 + do { + try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) + print("Success! Yum.") + } catch .invalidSelection { + print("Invalid Selection.") + } catch .outOfStock { + print("Out of Stock.") + } catch .insufficientFunds(let coinsNeeded) { + print("Insufficient funds. Please insert an additional \\(coinsNeeded) coins.") + } catch { + print("Unexpected error: \\(error).") + } + """ + + #expect( + generated.normalize() == expected.normalize() + ) + + print("Generated code:") + print(generated) + } + + @Test("Function with throws clause and unlabeled parameter generates correct syntax") + internal func testFunctionWithThrowsClauseAndUnlabeledParameter() throws { + let function = Function("summarize") { + Parameter(unlabeled: "ratings", type: "[Int]") + } _: { + Guard { + VariableExp("ratings").property("isEmpty").not() + } else: { + Throw(EnumCase("noRatings")) + } + }.throws("StatisticsError") + + let generated = function.generateCode() + let expected = """ + func summarize(_ ratings: [Int]) throws(StatisticsError) { + guard !ratings.isEmpty else { throw .noRatings } + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Async functionality generates correct syntax") + internal func testAsyncFunctionality() throws { + let asyncCode = Group { + Variable(.let, name: "data") { + Call("fetchUserData") { + ParameterExp(name: "id", value: Literal.integer(1)) + } + }.async() + Variable(.let, name: "posts") { + Call("fetchUserPosts") { + ParameterExp(name: "id", value: Literal.integer(1)) + } + }.async() + TupleAssignment( + ["fetchedData", "fetchedPosts"], + equals: Tuple { + VariableExp("data") + VariableExp("posts") + } + ).async().throwing() + } + + let generated = asyncCode.generateCode() + let expected = """ + async let data = fetchUserData(id: 1) + async let posts = fetchUserPosts(id: 1) + let (fetchedData, fetchedPosts) = try await (data, posts) + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift b/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift index d47974f..133d548 100644 --- a/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift +++ b/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift @@ -116,7 +116,10 @@ internal struct MainApplicationTests { internal func testMainApplicationErrorResponseFormat() throws { // Test the error response format that the main application would generate let testError = NSError( - domain: "TestDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "Test error message"]) + domain: "TestDomain", + code: 1, + userInfo: [NSLocalizedDescriptionKey: "Test error message"] + ) let errorResponse = ["error": testError.localizedDescription] let jsonData = try JSONSerialization.data(withJSONObject: errorResponse) diff --git a/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift index 3870889..3319c29 100644 --- a/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift @@ -47,7 +47,9 @@ internal struct OptionsMacroIntegrationTests { #expect( generated.contains( - "extension MockDictionaryEnum: MappedValueRepresentable, MappedValueRepresented")) + "extension MockDictionaryEnum: MappedValueRepresentable, MappedValueRepresented" + ) + ) #expect(generated.contains("typealias MappedType = String")) #expect(generated.contains("static let mappedValues: [Int: String]")) #expect(generated.contains("2: \"a\"")) @@ -172,7 +174,9 @@ internal struct OptionsMacroIntegrationTests { #expect( generated.contains( - "extension EmptyDictEnum: MappedValueRepresentable, MappedValueRepresented")) + "extension EmptyDictEnum: MappedValueRepresentable, MappedValueRepresented" + ) + ) #expect(generated.contains("typealias MappedType = String")) #expect(generated.contains("static let mappedValues: [Int: String] = [: ]")) } @@ -195,38 +199,4 @@ internal struct OptionsMacroIntegrationTests { #expect(generated.contains("\"case-with-dash\"")) #expect(generated.contains("\"caseWithCamelCase\"")) } - - // MARK: - API Validation Tests - - @Test internal func testNewSyntaxKitAPICompleteness() { - // Verify that all the new API components work together correctly - - // Test LiteralValue protocol - let array: [String] = ["a", "b", "c"] - #expect(array.typeName == "[String]") - #expect(array.literalString == "[\"a\", \"b\", \"c\"]") - - let dict: [Int: String] = [1: "a", 2: "b"] - #expect(dict.typeName == "[Int: String]") - #expect(dict.literalString.contains("1: \"a\"")) - #expect(dict.literalString.contains("2: \"b\"")) - - // Test Variable with static support - let staticVar = Variable(.let, name: "test", equals: array).withExplicitType().static() - let staticGenerated = staticVar.generateCode().normalize() - #expect(staticGenerated.contains("static let test: [String] = [\"a\", \"b\", \"c\"]")) - - // Test Extension with inheritance - let ext = Extension("Test") { - // Empty content - }.inherits("Protocol1", "Protocol2") - - let extGenerated = ext.generateCode().normalize() - #expect(extGenerated.contains("extension Test: Protocol1, Protocol2")) - - // Test TypeAlias - let alias = TypeAlias("MyType", equals: "String") - let aliasGenerated = alias.generateCode().normalize() - #expect(aliasGenerated.contains("typealias MyType = String")) - } } diff --git a/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTestsAPI.swift b/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTestsAPI.swift new file mode 100644 index 0000000..41a4701 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTestsAPI.swift @@ -0,0 +1,39 @@ +import Testing + +@testable import SyntaxKit + +internal struct OptionsMacroIntegrationTestsAPI { + // MARK: - API Validation Tests + + @Test internal func testNewSyntaxKitAPICompleteness() { + // Verify that all the new API components work together correctly + + // Test LiteralValue protocol + let array: [String] = ["a", "b", "c"] + #expect(array.typeName == "[String]") + #expect(array.literalString == "[\"a\", \"b\", \"c\"]") + + let dict: [Int: String] = [1: "a", 2: "b"] + #expect(dict.typeName == "[Int: String]") + #expect(dict.literalString.contains("1: \"a\"")) + #expect(dict.literalString.contains("2: \"b\"")) + + // Test Variable with static support + let staticVar = Variable(.let, name: "test", equals: array).withExplicitType().static() + let staticGenerated = staticVar.generateCode().normalize() + #expect(staticGenerated.contains("static let test: [String] = [\"a\", \"b\", \"c\"]")) + + // Test Extension with inheritance + let ext = Extension("Test") { + // Empty content + }.inherits("Protocol1", "Protocol2") + + let extGenerated = ext.generateCode().normalize() + #expect(extGenerated.contains("extension Test: Protocol1, Protocol2")) + + // Test TypeAlias + let alias = TypeAlias("MyType", equals: "String") + let aliasGenerated = alias.generateCode().normalize() + #expect(aliasGenerated.contains("typealias MyType = String")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/ThrowBasicTests.swift b/Tests/SyntaxKitTests/Unit/ThrowBasicTests.swift new file mode 100644 index 0000000..e6db237 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ThrowBasicTests.swift @@ -0,0 +1,92 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct ThrowBasicTests { + // MARK: - Basic Throw Tests + + @Test("Basic throw with enum case generates correct syntax") + internal func testBasicThrowWithEnumCase() throws { + let throwStatement = Throw(EnumCase("connectionFailed")) + + let generated = throwStatement.generateCode() + let expected = "throw .connectionFailed" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with enum case and type generates correct syntax") + internal func testThrowWithEnumCaseAndType() throws { + let throwStatement = Throw(EnumCase("connectionFailed")) + + let generated = throwStatement.generateCode() + let expected = "throw .connectionFailed" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with enum case with associated value generates correct syntax") + internal func testThrowWithEnumCaseWithAssociatedValue() throws { + let throwStatement = Throw( + EnumCase("invalidInput") + .associatedValue("fieldName", type: "String") + ) + + let generated = throwStatement.generateCode() + let expected = "throw .invalidInput(fieldName)" + + #expect(generated.normalize() == expected.normalize()) + } + + // MARK: - Throw with Different Expression Types + + @Test("Throw with string literal generates correct syntax") + internal func testThrowWithStringLiteral() throws { + let throwStatement = Throw(Literal.string("Custom error message")) + + let generated = throwStatement.generateCode() + let expected = "throw \"Custom error message\"" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with integer literal generates correct syntax") + internal func testThrowWithIntegerLiteral() throws { + let throwStatement = Throw(Literal.integer(404)) + + let generated = throwStatement.generateCode() + let expected = "throw 404" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with boolean literal generates correct syntax") + internal func testThrowWithBooleanLiteral() throws { + let throwStatement = Throw(Literal.boolean(true)) + + let generated = throwStatement.generateCode() + let expected = "throw true" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with variable expression generates correct syntax") + internal func testThrowWithVariableExpression() throws { + let throwStatement = Throw(VariableExp("customError")) + + let generated = throwStatement.generateCode() + let expected = "throw customError" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with property access generates correct syntax") + internal func testThrowWithPropertyAccess() throws { + let throwStatement = Throw(VariableExp("user").property("validationError")) + + let generated = throwStatement.generateCode() + let expected = "throw user.validationError" + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift b/Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift new file mode 100644 index 0000000..eb8700c --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift @@ -0,0 +1,131 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct ThrowComplexTests { + // MARK: - Complex Throw Expressions + + @Test("Throw with conditional expression generates correct syntax") + internal func testThrowWithConditionalExpression() throws { + let throwStatement = Throw( + If(VariableExp("isNetworkError")) { + EnumCase("connectionFailed") + } else: { + EnumCase("invalidInput") + } + ) + + let generated = throwStatement.generateCode() + let expected = "throw if isNetworkError { .connectionFailed } else { .invalidInput }" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with tuple expression generates correct syntax") + internal func testThrowWithTupleExpression() throws { + let throwStatement = Throw( + Tuple { + Literal.string("Error occurred") + Literal.integer(500) + } + ) + + let generated = throwStatement.generateCode() + let expected = "throw (\"Error occurred\", 500)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with array literal generates correct syntax") + internal func testThrowWithArrayLiteral() throws { + let throwStatement = Throw( + Literal.array([ + Literal.string("Error 1"), + Literal.string("Error 2"), + ]) + ) + + let generated = throwStatement.generateCode() + let expected = "throw [\"Error 1\", \"Error 2\"]" + + #expect(generated.normalize() == expected.normalize()) + } + + // MARK: - Integration Tests + + @Test("Throw in guard statement generates correct syntax") + internal func testThrowInGuardStatement() throws { + let guardStatement = Guard { + VariableExp("user").property("isValid").not() + } else: { + Throw(EnumCase("invalidUser")) + } + + let generated = guardStatement.generateCode() + let expected = "guard !user.isValid else { throw .invalidUser }" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw in function generates correct syntax") + internal func testThrowInFunction() throws { + let function = Function("validateUser") { + Parameter(name: "user", type: "User") + } _: { + Guard { + VariableExp("user").property("name").property("isEmpty").not() + } else: { + Throw(EnumCase("emptyName")) + } + Guard { + VariableExp("user").property("email").property("isEmpty").not() + } else: { + Throw(EnumCase("emptyEmail")) + } + }.throws("ValidationError") + + let generated = function.generateCode() + let expected = """ + func validateUser(user: User) throws(ValidationError) { + guard !user.name.isEmpty else { throw .emptyName } + guard !user.email.isEmpty else { throw .emptyEmail } + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw in async function generates correct syntax") + internal func testThrowInAsyncFunction() throws { + let function = Function("fetchUser") { + Parameter(name: "id", type: "Int") + } _: { + Guard { + VariableExp("id") > Literal.integer(0) + } else: { + Throw(EnumCase("invalidId")) + } + Variable(.let, name: "user") { + Call("fetchUserFromAPI") { + ParameterExp(name: "userId", value: VariableExp("id")) + } + }.async() + Guard { + VariableExp("user") != Literal.nil + } else: { + Throw(EnumCase("userNotFound")) + } + }.asyncThrows("NetworkError") + + let generated = function.generateCode() + let expected = """ + func fetchUser(id: Int) async throws(NetworkError) { + guard id > 0 else { throw .invalidId } + async let user = fetchUserFromAPI(userId: id) + guard user != nil else { throw .userNotFound } + } + """ + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/ThrowEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/ThrowEdgeCaseTests.swift new file mode 100644 index 0000000..c2a3b9b --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ThrowEdgeCaseTests.swift @@ -0,0 +1,37 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct ThrowEdgeCaseTests { + // MARK: - Edge Cases + + @Test("Throw with nil literal generates correct syntax") + internal func testThrowWithNilLiteral() throws { + let throwStatement = Throw(Literal.nil) + + let generated = throwStatement.generateCode() + let expected = "throw nil" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with float literal generates correct syntax") + internal func testThrowWithFloatLiteral() throws { + let throwStatement = Throw(Literal.float(3.14)) + + let generated = throwStatement.generateCode() + let expected = "throw 3.14" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with reference literal generates correct syntax") + internal func testThrowWithReferenceLiteral() throws { + let throwStatement = Throw(Literal.ref("globalError")) + + let generated = throwStatement.generateCode() + let expected = "throw globalError" + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/ThrowFunctionTests.swift b/Tests/SyntaxKitTests/Unit/ThrowFunctionTests.swift new file mode 100644 index 0000000..7432ff7 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/ThrowFunctionTests.swift @@ -0,0 +1,66 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct ThrowFunctionTests { + // MARK: - Throw with Function Calls + + @Test("Throw with function call generates correct syntax") + internal func testThrowWithFunctionCall() throws { + let throwStatement = Throw( + Call("createError") { + ParameterExp(name: "code", value: Literal.integer(500)) + ParameterExp(name: "message", value: Literal.string("Internal server error")) + } + ) + + let generated = throwStatement.generateCode() + let expected = "throw createError(code: 500, message: \"Internal server error\")" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with async function call generates correct syntax") + internal func testThrowWithAsyncFunctionCall() throws { + let throwStatement = Throw( + Call("fetchError") { + ParameterExp(name: "id", value: Literal.integer(123)) + }.async() + ) + + let generated = throwStatement.generateCode() + let expected = "throw await fetchError(id: 123)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with throwing function call generates correct syntax") + internal func testThrowWithThrowingFunctionCall() throws { + let throwStatement = Throw( + Call("parseError") { + ParameterExp(name: "data", value: VariableExp("jsonData")) + }.throwing() + ) + + let generated = throwStatement.generateCode() + let expected = "throw try parseError(data: jsonData)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throw with custom error type generates correct syntax") + internal func testThrowWithCustomErrorType() throws { + let throwStatement = Throw( + Call("CustomError") { + ParameterExp(name: "code", value: Literal.integer(404)) + ParameterExp(name: "message", value: Literal.string("Not found")) + ParameterExp(name: "details", value: VariableExp("errorDetails")) + } + ) + + let generated = throwStatement.generateCode() + let expected = "throw CustomError(code: 404, message: \"Not found\", details: errorDetails)" + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift b/Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift new file mode 100644 index 0000000..9578aba --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift @@ -0,0 +1,122 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct TupleAssignmentAsyncTests { + // MARK: - Async Tuple Assignment Tests + + @Test("Async tuple assignment generates correct syntax") + internal func testAsyncTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["data", "posts"], + equals: Tuple { + VariableExp("fetchData") + VariableExp("fetchPosts") + } + ).async() + + let generated = tupleAssignment.generateCode() + let expected = "let (data, posts) = await (fetchData, fetchPosts)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Async tuple assignment with mixed expressions generates correct syntax") + internal func testAsyncTupleAssignmentWithMixedExpressions() throws { + let tupleAssignment = TupleAssignment( + ["result", "count"], + equals: Tuple { + Call("processData") { + ParameterExp(name: "input", value: Literal.string("test")) + } + Literal.integer(42) + } + ).async() + + let generated = tupleAssignment.generateCode() + let expected = "let (result, count) = await (processData(input: \"test\"), 42)" + + #expect(generated.normalize() == expected.normalize()) + } + + // MARK: - Throwing Tuple Assignment Tests + + @Test("Throwing tuple assignment generates correct syntax") + internal func testThrowingTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["data", "posts"], + equals: Tuple { + VariableExp("fetchData") + VariableExp("fetchPosts") + } + ).throwing() + + let generated = tupleAssignment.generateCode() + let expected = "let (data, posts) = try (fetchData, fetchPosts)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Throwing tuple assignment with async calls generates correct syntax") + internal func testThrowingTupleAssignmentWithAsyncCalls() throws { + let tupleAssignment = TupleAssignment( + ["data", "posts"], + equals: Tuple { + Call("fetchUserData") { + ParameterExp(name: "id", value: Literal.integer(1)) + }.async() + Call("fetchUserPosts") { + ParameterExp(name: "id", value: Literal.integer(1)) + }.async() + } + ).throwing() + + let generated = tupleAssignment.generateCode() + let expected = + "let (data, posts) = try (await fetchUserData(id: 1), await fetchUserPosts(id: 1))" + + #expect(generated.normalize() == expected.normalize()) + } + + // MARK: - Async and Throwing Tuple Assignment Tests + + @Test("Async and throwing tuple assignment generates correct syntax") + internal func testAsyncAndThrowingTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["data", "posts"], + equals: Tuple { + VariableExp("fetchData") + VariableExp("fetchPosts") + } + ).async().throwing() + + let generated = tupleAssignment.generateCode() + let expected = "let (data, posts) = try await (fetchData, fetchPosts)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Async and throwing tuple assignment with complex expressions generates correct syntax") + internal func testAsyncAndThrowingTupleAssignmentWithComplexExpressions() throws { + let tupleAssignment = TupleAssignment( + ["user", "profile", "settings"], + equals: Tuple { + Call("fetchUser") { + ParameterExp(name: "id", value: Literal.integer(123)) + }.async() + Call("fetchProfile") { + ParameterExp(name: "userId", value: Literal.integer(123)) + }.async() + Call("fetchSettings") { + ParameterExp(name: "userId", value: Literal.integer(123)) + }.async() + } + ).async().throwing() + + let generated = tupleAssignment.generateCode() + let expected = + "let (user, profile, settings) = try await (await fetchUser(id: 123), await fetchProfile(userId: 123), await fetchSettings(userId: 123))" + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentBasicTests.swift b/Tests/SyntaxKitTests/Unit/TupleAssignmentBasicTests.swift new file mode 100644 index 0000000..47889a5 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/TupleAssignmentBasicTests.swift @@ -0,0 +1,72 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct TupleAssignmentBasicTests { + // MARK: - Basic Tuple Assignment Tests + + @Test("Basic tuple assignment generates correct syntax") + internal func testBasicTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["x", "y"], + equals: Tuple { + Literal.integer(1) + Literal.integer(2) + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (x, y) = (1, 2)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Single element tuple assignment generates correct syntax") + internal func testSingleElementTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["value"], + equals: Tuple { + Literal.string("test") + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (value) = (\"test\")" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Three element tuple assignment generates correct syntax") + internal func testThreeElementTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["x", "y", "z"], + equals: Tuple { + Literal.integer(1) + Literal.integer(2) + Literal.integer(3) + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (x, y, z) = (1, 2, 3)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Tuple assignment with mixed literal types generates correct syntax") + internal func testTupleAssignmentWithMixedTypes() throws { + let tupleAssignment = TupleAssignment( + ["name", "age", "isActive"], + equals: Tuple { + Literal.string("John") + Literal.integer(30) + Literal.boolean(true) + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (name, age, isActive) = (\"John\", 30, true)" + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/TupleAssignmentEdgeCaseTests.swift new file mode 100644 index 0000000..ced5f47 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/TupleAssignmentEdgeCaseTests.swift @@ -0,0 +1,82 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct TupleAssignmentEdgeCaseTests { + // MARK: - Edge Cases and Error Handling Tests + + @Test("Tuple assignment with empty elements array throws error") + internal func testTupleAssignmentWithEmptyElements() throws { + // This should be handled gracefully by the DSL + let tupleAssignment = TupleAssignment( + [], + equals: Tuple { + Literal.integer(1) + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let () = (1)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Tuple assignment with variable expressions generates correct syntax") + internal func testTupleAssignmentWithVariableExpressions() throws { + let tupleAssignment = TupleAssignment( + ["firstName", "lastName"], + equals: Tuple { + VariableExp("user.firstName") + VariableExp("user.lastName") + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (firstName, lastName) = (user.firstName, user.lastName)" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Tuple assignment with function calls generates correct syntax") + internal func testTupleAssignmentWithFunctionCalls() throws { + let tupleAssignment = TupleAssignment( + ["min", "max"], + equals: Tuple { + Call("findMinimum") { + ParameterExp(name: "array", value: VariableExp("numbers")) + } + Call("findMaximum") { + ParameterExp(name: "array", value: VariableExp("numbers")) + } + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (min, max) = (findMinimum(array: numbers), findMaximum(array: numbers))" + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Tuple assignment with nested tuples generates correct syntax") + internal func testTupleAssignmentWithNestedTuples() throws { + let tupleAssignment = TupleAssignment( + ["point", "color"], + equals: Tuple { + Tuple { + Literal.integer(10) + Literal.integer(20) + } + Tuple { + Literal.integer(255) + Literal.integer(0) + Literal.integer(0) + } + } + ) + + let generated = tupleAssignment.generateCode() + let expected = "let (point, color) = ((10, 20), (255, 0, 0))" + + #expect(generated.normalize() == expected.normalize()) + } +} diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/TupleAssignmentIntegrationTests.swift new file mode 100644 index 0000000..9e1ee18 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/TupleAssignmentIntegrationTests.swift @@ -0,0 +1,96 @@ +import Testing + +@testable import SyntaxKit + +@Suite internal struct TupleAssignmentIntegrationTests { + // MARK: - Integration Tests + + @Test("Tuple assignment in a function generates correct syntax") + internal func testTupleAssignmentInFunction() throws { + let function = Function("processData") { + Parameter(name: "input", type: "[Int]") + } _: { + TupleAssignment( + ["sum", "count"], + equals: Tuple { + Call("calculateSum") { + ParameterExp(name: "numbers", value: VariableExp("input")) + } + Call("calculateCount") { + ParameterExp(name: "numbers", value: VariableExp("input")) + } + } + ) + Call("print") { + ParameterExp( + unlabeled: Literal.string("Sum: \\(sum), Count: \\(count)") + ) + } + } + + let generated = function.generateCode() + let expected = """ + func processData(input: [Int]) { + let (sum, count) = (calculateSum(numbers: input), calculateCount(numbers: input)) + print("Sum: \\(sum), Count: \\(count)") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("Async tuple assignment in async function generates correct syntax") + internal func testAsyncTupleAssignmentInAsyncFunction() throws { + let function = Function("fetchUserData") { + Parameter(name: "userId", type: "Int") + } _: { + TupleAssignment( + ["user", "posts"], + equals: Tuple { + Call("fetchUser") { + ParameterExp(name: "id", value: VariableExp("userId")) + }.async() + Call("fetchPosts") { + ParameterExp(name: "userId", value: VariableExp("userId")) + }.async() + } + ).async().throwing() + Call("print") { + ParameterExp( + unlabeled: Literal.string("User: \\(user.name), Posts: \\(posts.count)") + ) + } + }.async().throws("NetworkError") + + let generated = function.generateCode() + let expected = """ + func fetchUserData(userId: Int) async throws(NetworkError) { + let (user, posts) = try await (await fetchUser(id: userId), await fetchPosts(userId: userId)) + print("User: \\(user.name), Posts: \\(posts.count)") + } + """ + + #expect(generated.normalize() == expected.normalize()) + } + + @Test("AsyncSet tuple assignment generates concurrent async let pattern") + internal func testAsyncSetTupleAssignment() throws { + let tupleAssignment = TupleAssignment( + ["data", "posts"], + equals: Tuple { + Call("fetchUserData") { + ParameterExp(name: "id", value: Literal.integer(1)) + } + Call("fetchUserPosts") { + ParameterExp(name: "id", value: Literal.integer(1)) + } + } + ).asyncSet().throwing() + + let generated = tupleAssignment.generateCode() + let expected = """ + async let (data, posts) = try await (fetchUserData(id: 1), fetchUserPosts(id: 1)) + """ + #expect(generated.normalize() == expected.normalize()) + } +} From 47d4b413406f4e409b2a2d82a76b57b0809bba49 Mon Sep 17 00:00:00 2001 From: leogdion Date: Sun, 22 Jun 2025 18:46:40 -0400 Subject: [PATCH 07/10] Fixing Most Linting and Code Coverage Issues (#79) --- .swiftlint.yml | 2 +- .../{ => Attributes}/Attribute.swift | 0 .../{ => Attributes}/Trivia+Comments.swift | 0 .../CodeBlock+ExprSyntax.swift | 0 .../{ => CodeBlocks}/CodeBlock+Generate.swift | 26 +- .../CodeBlocks/CodeBlockBuilder.swift | 38 +++ .../CodeBlockBuilderResult.swift} | 25 +- .../CodeBlocks/CodeBlockItemSyntax.Item.swift | 62 +++++ .../{ => CodeBlocks}/CommentedCodeBlock.swift | 4 +- .../SyntaxKit/CodeBlocks/EmptyCodeBlock.swift | 39 +++ .../{ => CodeBlocks}/ExprCodeBlock.swift | 0 .../Array+LiteralValue.swift | 3 +- .../{ => Collections}/ArrayLiteral.swift | 4 +- .../Dictionary+LiteralValue.swift | 3 +- .../{ => Collections}/DictionaryExpr.swift | 12 +- .../{ => Collections}/DictionaryLiteral.swift | 2 +- .../{ => Collections}/DictionaryValue.swift | 0 .../SyntaxKit/{ => Collections}/Tuple.swift | 0 .../TupleAssignment+AsyncSet.swift | 6 +- .../{ => Collections}/TupleAssignment.swift | 7 +- .../{ => Collections}/TupleLiteral.swift | 2 +- .../{ => Collections}/TuplePattern.swift | 0 .../TuplePatternCodeBlock.swift | 0 Sources/SyntaxKit/{ => ControlFlow}/Do.swift | 0 Sources/SyntaxKit/{ => ControlFlow}/For.swift | 3 +- .../SyntaxKit/{ => ControlFlow}/Guard.swift | 0 Sources/SyntaxKit/ControlFlow/If+Body.swift | 50 ++++ .../ControlFlow/If+CodeBlockItem.swift | 47 ++++ .../SyntaxKit/ControlFlow/If+Conditions.swift | 92 +++++++ .../SyntaxKit/ControlFlow/If+ElseBody.swift | 144 +++++++++++ Sources/SyntaxKit/ControlFlow/If.swift | 86 +++++++ .../SyntaxKit/{ => ControlFlow}/Switch.swift | 12 +- .../{ => ControlFlow}/SwitchCase.swift | 17 +- .../{ => ControlFlow}/SwitchLet.swift | 7 +- .../SyntaxKit/{ => ControlFlow}/While.swift | 15 +- Sources/SyntaxKit/Core/CodeBlock.swift | 37 +++ Sources/SyntaxKit/{ => Core}/Line.swift | 21 -- .../SyntaxKit/Core/PatternConvertible.swift | 37 +++ .../SyntaxKit/{ => Declarations}/Class.swift | 4 +- .../SyntaxKit/{ => Declarations}/Enum.swift | 10 +- .../{ => Declarations}/Extension.swift | 7 +- .../SyntaxKit/{ => Declarations}/Init.swift | 15 +- .../{ => Declarations}/Protocol.swift | 4 +- .../SyntaxKit/{ => Declarations}/Struct.swift | 10 +- .../{ => Declarations}/TypeAlias.swift | 0 .../SyntaxKit/{ => ErrorHandling}/Catch.swift | 3 +- .../ErrorHandling/CatchBuilder.swift | 157 ++++++++++++ .../SyntaxKit/{ => ErrorHandling}/Throw.swift | 0 .../{ => Expressions}/Assignment.swift | 0 .../SyntaxKit/{ => Expressions}/Call.swift | 16 +- .../Expressions/FunctionCallExp.swift | 103 ++++++++ .../SyntaxKit/{ => Expressions}/Infix.swift | 73 ++---- .../Literal+Convenience.swift | 0 .../Literal+ExprCodeBlock.swift | 51 +++- .../Literal+PatternConvertible.swift | 40 ++++ .../SyntaxKit/{ => Expressions}/Literal.swift | 0 .../{ => Expressions}/LiteralValue.swift | 0 .../NegatedPropertyAccessExp.swift} | 52 ++-- .../{ => Expressions}/PlusAssign.swift | 8 +- .../Expressions/PropertyAccessExp.swift | 80 +++++++ .../SyntaxKit/{ => Expressions}/Return.swift | 0 .../Function+EffectSpecifiers.swift | 4 +- .../{ => Functions}/Function+Effects.swift | 0 .../{ => Functions}/Function+Modifiers.swift | 0 .../{ => Functions}/Function+Syntax.swift | 73 ++---- .../SyntaxKit/{ => Functions}/Function.swift | 6 +- .../FunctionParameterSyntax+Init.swift | 114 +++++++++ .../{ => Functions}/FunctionRequirement.swift | 10 +- Sources/SyntaxKit/If.swift | 224 ------------------ .../{ => Parameters}/Parameter.swift | 8 - .../ParameterBuilderResult.swift | 0 .../{ => Parameters}/ParameterExp.swift | 0 .../ParameterExpBuilderResult.swift | 0 Sources/SyntaxKit/PatternConvertible.swift | 127 ---------- .../Patterns/Int+PatternConvertible.swift | 38 +++ .../Patterns/LetBindingPattern.swift | 61 +++++ .../Patterns/Range+PatternConvertible.swift | 68 ++++++ .../Patterns/String+PatternConvertible.swift | 37 +++ Sources/SyntaxKit/{ => Utilities}/Break.swift | 0 Sources/SyntaxKit/{ => Utilities}/Case.swift | 6 +- .../CommentBuilderResult.swift | 0 .../SyntaxKit/{ => Utilities}/Continue.swift | 0 .../SyntaxKit/{ => Utilities}/Default.swift | 0 .../{ => Utilities}/EnumCase+Syntax.swift | 0 .../SyntaxKit/{ => Utilities}/EnumCase.swift | 6 +- .../{ => Utilities}/Fallthrough.swift | 0 Sources/SyntaxKit/{ => Utilities}/Group.swift | 0 Sources/SyntaxKit/{ => Utilities}/Let.swift | 0 .../{ => Utilities}/Parenthesized.swift | 0 .../{ => Utilities}/PropertyRequirement.swift | 0 Sources/SyntaxKit/{ => Utilities}/Then.swift | 0 Sources/SyntaxKit/VariableExp.swift | 214 ----------------- .../{ => Variables}/ComputedProperty.swift | 4 +- .../Variable+LiteralInitializers.swift | 6 +- .../Variable+TypedInitializers.swift | 31 ++- .../SyntaxKit/{ => Variables}/Variable.swift | 0 .../{ => Variables}/VariableDecl.swift | 0 Sources/SyntaxKit/Variables/VariableExp.swift | 74 ++++++ .../{ => Variables}/VariableKind.swift | 0 Sources/SyntaxKit/parser/String.swift | 6 +- Sources/SyntaxKit/parser/TokenVisitor.swift | 17 +- Sources/SyntaxKit/parser/TreeNode.swift | 6 +- .../Integration/ConcurrencyExampleTests.swift | 11 +- .../ConditionalsExampleTests.swift | 46 ++-- .../{ => Attributes}/AttributeTests.swift | 0 .../TupleAssignmentAsyncTests.swift | 7 +- .../TupleAssignmentBasicTests.swift | 0 .../TupleAssignmentEdgeCaseTests.swift | 0 .../TupleAssignmentIntegrationTests.swift | 0 .../{ => ControlFlow}/ConditionalsTests.swift | 0 .../Unit/{ => ControlFlow}/ForLoopTests.swift | 6 +- .../{ => Core}/PatternConvertibleTests.swift | 0 .../Unit/{ => Declarations}/ClassTests.swift | 0 .../{ => Declarations}/ExtensionTests.swift | 0 .../{ => Declarations}/ProtocolTests.swift | 0 .../Unit/{ => Declarations}/StructTests.swift | 0 .../{ => Declarations}/TypeAliasTests.swift | 0 .../Unit/{ => EdgeCases}/EdgeCaseTests.swift | 0 .../EdgeCaseTestsExpressions.swift | 0 .../{ => EdgeCases}/EdgeCaseTestsTypes.swift | 0 .../{ => ErrorHandling}/CatchBasicTests.swift | 3 +- .../CatchComplexTests.swift | 18 +- .../CatchEdgeCaseTests.swift | 0 .../CatchIntegrationTests.swift | 0 .../{ => ErrorHandling}/DoBasicTests.swift | 0 .../{ => ErrorHandling}/DoComplexTests.swift | 0 .../{ => ErrorHandling}/DoEdgeCaseTests.swift | 0 .../DoIntegrationTests.swift | 0 .../ErrorHandlingTests.swift | 14 +- .../{ => ErrorHandling}/ThrowBasicTests.swift | 0 .../ThrowComplexTests.swift | 4 +- .../ThrowEdgeCaseTests.swift | 0 .../ThrowFunctionTests.swift | 0 .../Unit/{ => Expressions}/CallTests.swift | 0 .../Unit/{ => Expressions}/LiteralTests.swift | 0 .../{ => Expressions}/LiteralValueTests.swift | 0 .../Unit/{ => Functions}/FunctionTests.swift | 23 +- .../FrameworkCompatibilityTests.swift | 0 .../OptionsMacroIntegrationTests.swift | 0 .../OptionsMacroIntegrationTestsAPI.swift | 0 .../Unit/MainApplicationTests.swift | 198 ---------------- .../AssertionMigrationTests.swift | 0 .../CodeStyleMigrationTests.swift | 4 +- .../Unit/{ => Migration}/MigrationTests.swift | 5 +- .../{ => Utilities}/String+Normalize.swift | 0 .../{ => Variables}/VariableStaticTests.swift | 3 +- 146 files changed, 1808 insertions(+), 1110 deletions(-) rename Sources/SyntaxKit/{ => Attributes}/Attribute.swift (100%) rename Sources/SyntaxKit/{ => Attributes}/Trivia+Comments.swift (100%) rename Sources/SyntaxKit/{ => CodeBlocks}/CodeBlock+ExprSyntax.swift (100%) rename Sources/SyntaxKit/{ => CodeBlocks}/CodeBlock+Generate.swift (63%) create mode 100644 Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift rename Sources/SyntaxKit/{CodeBlock.swift => CodeBlocks/CodeBlockBuilderResult.swift} (74%) create mode 100644 Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift rename Sources/SyntaxKit/{ => CodeBlocks}/CommentedCodeBlock.swift (97%) create mode 100644 Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift rename Sources/SyntaxKit/{ => CodeBlocks}/ExprCodeBlock.swift (100%) rename Sources/SyntaxKit/{ => Collections}/Array+LiteralValue.swift (98%) rename Sources/SyntaxKit/{ => Collections}/ArrayLiteral.swift (96%) rename Sources/SyntaxKit/{ => Collections}/Dictionary+LiteralValue.swift (98%) rename Sources/SyntaxKit/{ => Collections}/DictionaryExpr.swift (90%) rename Sources/SyntaxKit/{ => Collections}/DictionaryLiteral.swift (98%) rename Sources/SyntaxKit/{ => Collections}/DictionaryValue.swift (100%) rename Sources/SyntaxKit/{ => Collections}/Tuple.swift (100%) rename Sources/SyntaxKit/{ => Collections}/TupleAssignment+AsyncSet.swift (92%) rename Sources/SyntaxKit/{ => Collections}/TupleAssignment.swift (98%) rename Sources/SyntaxKit/{ => Collections}/TupleLiteral.swift (98%) rename Sources/SyntaxKit/{ => Collections}/TuplePattern.swift (100%) rename Sources/SyntaxKit/{ => Collections}/TuplePatternCodeBlock.swift (100%) rename Sources/SyntaxKit/{ => ControlFlow}/Do.swift (100%) rename Sources/SyntaxKit/{ => ControlFlow}/For.swift (99%) rename Sources/SyntaxKit/{ => ControlFlow}/Guard.swift (100%) create mode 100644 Sources/SyntaxKit/ControlFlow/If+Body.swift create mode 100644 Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift create mode 100644 Sources/SyntaxKit/ControlFlow/If+Conditions.swift create mode 100644 Sources/SyntaxKit/ControlFlow/If+ElseBody.swift create mode 100644 Sources/SyntaxKit/ControlFlow/If.swift rename Sources/SyntaxKit/{ => ControlFlow}/Switch.swift (90%) rename Sources/SyntaxKit/{ => ControlFlow}/SwitchCase.swift (95%) rename Sources/SyntaxKit/{ => ControlFlow}/SwitchLet.swift (94%) rename Sources/SyntaxKit/{ => ControlFlow}/While.swift (94%) create mode 100644 Sources/SyntaxKit/Core/CodeBlock.swift rename Sources/SyntaxKit/{ => Core}/Line.swift (73%) create mode 100644 Sources/SyntaxKit/Core/PatternConvertible.swift rename Sources/SyntaxKit/{ => Declarations}/Class.swift (99%) rename Sources/SyntaxKit/{ => Declarations}/Enum.swift (97%) rename Sources/SyntaxKit/{ => Declarations}/Extension.swift (98%) rename Sources/SyntaxKit/{ => Declarations}/Init.swift (90%) rename Sources/SyntaxKit/{ => Declarations}/Protocol.swift (99%) rename Sources/SyntaxKit/{ => Declarations}/Struct.swift (97%) rename Sources/SyntaxKit/{ => Declarations}/TypeAlias.swift (100%) rename Sources/SyntaxKit/{ => ErrorHandling}/Catch.swift (99%) create mode 100644 Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift rename Sources/SyntaxKit/{ => ErrorHandling}/Throw.swift (100%) rename Sources/SyntaxKit/{ => Expressions}/Assignment.swift (100%) rename Sources/SyntaxKit/{ => Expressions}/Call.swift (91%) create mode 100644 Sources/SyntaxKit/Expressions/FunctionCallExp.swift rename Sources/SyntaxKit/{ => Expressions}/Infix.swift (56%) rename Sources/SyntaxKit/{ => Expressions}/Literal+Convenience.swift (100%) rename Sources/SyntaxKit/{ => Expressions}/Literal+ExprCodeBlock.swift (77%) create mode 100644 Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift rename Sources/SyntaxKit/{ => Expressions}/Literal.swift (100%) rename Sources/SyntaxKit/{ => Expressions}/LiteralValue.swift (100%) rename Sources/SyntaxKit/{CatchBuilder.swift => Expressions/NegatedPropertyAccessExp.swift} (56%) rename Sources/SyntaxKit/{ => Expressions}/PlusAssign.swift (94%) create mode 100644 Sources/SyntaxKit/Expressions/PropertyAccessExp.swift rename Sources/SyntaxKit/{ => Expressions}/Return.swift (100%) rename Sources/SyntaxKit/{ => Functions}/Function+EffectSpecifiers.swift (96%) rename Sources/SyntaxKit/{ => Functions}/Function+Effects.swift (100%) rename Sources/SyntaxKit/{ => Functions}/Function+Modifiers.swift (100%) rename Sources/SyntaxKit/{ => Functions}/Function+Syntax.swift (70%) rename Sources/SyntaxKit/{ => Functions}/Function.swift (96%) create mode 100644 Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift rename Sources/SyntaxKit/{ => Functions}/FunctionRequirement.swift (96%) delete mode 100644 Sources/SyntaxKit/If.swift rename Sources/SyntaxKit/{ => Parameters}/Parameter.swift (92%) rename Sources/SyntaxKit/{ => Parameters}/ParameterBuilderResult.swift (100%) rename Sources/SyntaxKit/{ => Parameters}/ParameterExp.swift (100%) rename Sources/SyntaxKit/{ => Parameters}/ParameterExpBuilderResult.swift (100%) delete mode 100644 Sources/SyntaxKit/PatternConvertible.swift create mode 100644 Sources/SyntaxKit/Patterns/Int+PatternConvertible.swift create mode 100644 Sources/SyntaxKit/Patterns/LetBindingPattern.swift create mode 100644 Sources/SyntaxKit/Patterns/Range+PatternConvertible.swift create mode 100644 Sources/SyntaxKit/Patterns/String+PatternConvertible.swift rename Sources/SyntaxKit/{ => Utilities}/Break.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Case.swift (99%) rename Sources/SyntaxKit/{ => Utilities}/CommentBuilderResult.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Continue.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Default.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/EnumCase+Syntax.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/EnumCase.swift (98%) rename Sources/SyntaxKit/{ => Utilities}/Fallthrough.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Group.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Let.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Parenthesized.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/PropertyRequirement.swift (100%) rename Sources/SyntaxKit/{ => Utilities}/Then.swift (100%) delete mode 100644 Sources/SyntaxKit/VariableExp.swift rename Sources/SyntaxKit/{ => Variables}/ComputedProperty.swift (99%) rename Sources/SyntaxKit/{ => Variables}/Variable+LiteralInitializers.swift (97%) rename Sources/SyntaxKit/{ => Variables}/Variable+TypedInitializers.swift (88%) rename Sources/SyntaxKit/{ => Variables}/Variable.swift (100%) rename Sources/SyntaxKit/{ => Variables}/VariableDecl.swift (100%) create mode 100644 Sources/SyntaxKit/Variables/VariableExp.swift rename Sources/SyntaxKit/{ => Variables}/VariableKind.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Attributes}/AttributeTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Collections}/TupleAssignmentAsyncTests.swift (94%) rename Tests/SyntaxKitTests/Unit/{ => Collections}/TupleAssignmentBasicTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Collections}/TupleAssignmentEdgeCaseTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Collections}/TupleAssignmentIntegrationTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ControlFlow}/ConditionalsTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ControlFlow}/ForLoopTests.swift (88%) rename Tests/SyntaxKitTests/Unit/{ => Core}/PatternConvertibleTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Declarations}/ClassTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Declarations}/ExtensionTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Declarations}/ProtocolTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Declarations}/StructTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Declarations}/TypeAliasTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => EdgeCases}/EdgeCaseTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => EdgeCases}/EdgeCaseTestsExpressions.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => EdgeCases}/EdgeCaseTestsTypes.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/CatchBasicTests.swift (97%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/CatchComplexTests.swift (86%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/CatchEdgeCaseTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/CatchIntegrationTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/DoBasicTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/DoComplexTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/DoEdgeCaseTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/DoIntegrationTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/ErrorHandlingTests.swift (90%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/ThrowBasicTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/ThrowComplexTests.swift (96%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/ThrowEdgeCaseTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => ErrorHandling}/ThrowFunctionTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Expressions}/CallTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Expressions}/LiteralTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Expressions}/LiteralValueTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Functions}/FunctionTests.swift (86%) rename Tests/SyntaxKitTests/Unit/{ => Integration}/FrameworkCompatibilityTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Integration}/OptionsMacroIntegrationTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Integration}/OptionsMacroIntegrationTestsAPI.swift (100%) delete mode 100644 Tests/SyntaxKitTests/Unit/MainApplicationTests.swift rename Tests/SyntaxKitTests/Unit/{ => Migration}/AssertionMigrationTests.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Migration}/CodeStyleMigrationTests.swift (95%) rename Tests/SyntaxKitTests/Unit/{ => Migration}/MigrationTests.swift (98%) rename Tests/SyntaxKitTests/Unit/{ => Utilities}/String+Normalize.swift (100%) rename Tests/SyntaxKitTests/Unit/{ => Variables}/VariableStaticTests.swift (99%) diff --git a/.swiftlint.yml b/.swiftlint.yml index 91eed35..f9212ce 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -11,7 +11,6 @@ opt_in_rules: - contains_over_range_nil_comparison - convenience_type - discouraged_object_literal - - discouraged_optional_boolean - empty_collection_literal - empty_count - empty_string @@ -121,6 +120,7 @@ excluded: - Mint - Examples - Macros + - Sources/SyntaxKit/parser indentation_width: indentation_width: 2 file_name: diff --git a/Sources/SyntaxKit/Attribute.swift b/Sources/SyntaxKit/Attributes/Attribute.swift similarity index 100% rename from Sources/SyntaxKit/Attribute.swift rename to Sources/SyntaxKit/Attributes/Attribute.swift diff --git a/Sources/SyntaxKit/Trivia+Comments.swift b/Sources/SyntaxKit/Attributes/Trivia+Comments.swift similarity index 100% rename from Sources/SyntaxKit/Trivia+Comments.swift rename to Sources/SyntaxKit/Attributes/Trivia+Comments.swift diff --git a/Sources/SyntaxKit/CodeBlock+ExprSyntax.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlock+ExprSyntax.swift similarity index 100% rename from Sources/SyntaxKit/CodeBlock+ExprSyntax.swift rename to Sources/SyntaxKit/CodeBlocks/CodeBlock+ExprSyntax.swift diff --git a/Sources/SyntaxKit/CodeBlock+Generate.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift similarity index 63% rename from Sources/SyntaxKit/CodeBlock+Generate.swift rename to Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift index ecde6e4..adfd488 100644 --- a/Sources/SyntaxKit/CodeBlock+Generate.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift @@ -42,30 +42,12 @@ extension CodeBlock { statements = codeBlock.statements } else { let item: CodeBlockItemSyntax.Item - if let decl = self.syntax.as(DeclSyntax.self) { - item = .decl(decl) - } else if let stmt = self.syntax.as(StmtSyntax.self) { - item = .stmt(stmt) - } else if let expr = self.syntax.as(ExprSyntax.self) { - item = .expr(expr) - } else if let token = self.syntax.as(TokenSyntax.self) { - // Wrap TokenSyntax in DeclReferenceExprSyntax and then in ExprSyntax - let expr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) - item = .expr(expr) - } else if let switchCase = self.syntax.as(SwitchCaseSyntax.self) { - // Wrap SwitchCaseSyntax in a SwitchExprSyntax and treat it as an expression - // This is a fallback for when SwitchCase is used standalone - let switchExpr = SwitchExprSyntax( - switchKeyword: .keyword(.switch, trailingTrivia: .space), - subject: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_"))), - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - cases: SwitchCaseListSyntax([SwitchCaseListSyntax.Element(switchCase)]), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - item = .expr(ExprSyntax(switchExpr)) + if let convertedItem = CodeBlockItemSyntax.Item.create(from: self.syntax) { + item = convertedItem } else { fatalError( - "Unsupported syntax type at top level: \(type(of: self.syntax)) (\(self.syntax)) generating from \(self)" + "Unsupported syntax type at top level: \(type(of: self.syntax)) (\(self.syntax)) " + + "generating from \(self)" ) } statements = CodeBlockItemListSyntax([ diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift new file mode 100644 index 0000000..74c241f --- /dev/null +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift @@ -0,0 +1,38 @@ +// +// CodeBlockBuilder.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// A protocol for types that can build a ``CodeBlock``. +public protocol CodeBlockBuilder { + /// The type of ``CodeBlock`` that this builder creates. + associatedtype Result: CodeBlock + /// Builds the ``CodeBlock``. + func build() -> Result +} diff --git a/Sources/SyntaxKit/CodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift similarity index 74% rename from Sources/SyntaxKit/CodeBlock.swift rename to Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift index 086e2a1..4340d5c 100644 --- a/Sources/SyntaxKit/CodeBlock.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift @@ -1,5 +1,5 @@ // -// CodeBlock.swift +// CodeBlockBuilderResult.swift // SyntaxKit // // Created by Leo Dion. @@ -28,21 +28,6 @@ // import Foundation -import SwiftSyntax - -/// A protocol for types that can be represented as a SwiftSyntax node. -public protocol CodeBlock { - /// The SwiftSyntax representation of the code block. - var syntax: SyntaxProtocol { get } -} - -/// A protocol for types that can build a ``CodeBlock``. -public protocol CodeBlockBuilder { - /// The type of ``CodeBlock`` that this builder creates. - associatedtype Result: CodeBlock - /// Builds the ``CodeBlock``. - func build() -> Result -} /// A result builder for creating arrays of ``CodeBlock``s. @resultBuilder @@ -72,11 +57,3 @@ public enum CodeBlockBuilderResult { components } } - -/// An empty ``CodeBlock``. -public struct EmptyCodeBlock: CodeBlock { - /// The syntax for an empty code block. - public var syntax: SyntaxProtocol { - StringSegmentSyntax(content: .unknown("")) - } -} diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift new file mode 100644 index 0000000..17e72fe --- /dev/null +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift @@ -0,0 +1,62 @@ +// +// CodeBlockItemSyntax.Item.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension CodeBlockItemSyntax.Item { + /// Creates a `CodeBlockItemSyntax.Item` from a `SyntaxProtocol`. + /// - Parameter syntax: The syntax to convert. + /// - Returns: A `CodeBlockItemSyntax.Item` if the conversion is successful, `nil` otherwise. + public static func create(from syntax: SyntaxProtocol) -> CodeBlockItemSyntax.Item? { + if let decl = syntax.as(DeclSyntax.self) { + return .decl(decl) + } else if let stmt = syntax.as(StmtSyntax.self) { + return .stmt(stmt) + } else if let expr = syntax.as(ExprSyntax.self) { + return .expr(expr) + } else if let token = syntax.as(TokenSyntax.self) { + // Wrap TokenSyntax in DeclReferenceExprSyntax and then in ExprSyntax + let expr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) + return .expr(expr) + } else if let switchCase = syntax.as(SwitchCaseSyntax.self) { + // Wrap SwitchCaseSyntax in a SwitchExprSyntax and treat it as an expression + // This is a fallback for when SwitchCase is used standalone + let switchExpr = SwitchExprSyntax( + switchKeyword: .keyword(.switch, trailingTrivia: .space), + subject: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_"))), + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + cases: SwitchCaseListSyntax([SwitchCaseListSyntax.Element(switchCase)]), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + return .expr(ExprSyntax(switchExpr)) + } else { + return nil + } + } +} diff --git a/Sources/SyntaxKit/CommentedCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift similarity index 97% rename from Sources/SyntaxKit/CommentedCodeBlock.swift rename to Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift index 79f6ef3..606f1c4 100644 --- a/Sources/SyntaxKit/CommentedCodeBlock.swift +++ b/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift @@ -38,7 +38,9 @@ internal struct CommentedCodeBlock: CodeBlock { internal var syntax: SyntaxProtocol { // Shortcut if there are no comment lines - guard !lines.isEmpty else { return base.syntax } + guard !lines.isEmpty else { + return base.syntax + } let commentTrivia = Trivia(pieces: lines.flatMap { [$0.triviaPiece, TriviaPiece.newlines(1)] }) diff --git a/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift new file mode 100644 index 0000000..6db397c --- /dev/null +++ b/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift @@ -0,0 +1,39 @@ +// +// EmptyCodeBlock.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// An empty ``CodeBlock``. +public struct EmptyCodeBlock: CodeBlock { + /// The syntax for an empty code block. + public var syntax: SyntaxProtocol { + StringSegmentSyntax(content: .unknown("")) + } +} diff --git a/Sources/SyntaxKit/ExprCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/ExprCodeBlock.swift similarity index 100% rename from Sources/SyntaxKit/ExprCodeBlock.swift rename to Sources/SyntaxKit/CodeBlocks/ExprCodeBlock.swift diff --git a/Sources/SyntaxKit/Array+LiteralValue.swift b/Sources/SyntaxKit/Collections/Array+LiteralValue.swift similarity index 98% rename from Sources/SyntaxKit/Array+LiteralValue.swift rename to Sources/SyntaxKit/Collections/Array+LiteralValue.swift index baf3c7b..9b75416 100644 --- a/Sources/SyntaxKit/Array+LiteralValue.swift +++ b/Sources/SyntaxKit/Collections/Array+LiteralValue.swift @@ -45,7 +45,8 @@ extension Array: LiteralValue where Element == String { .replacingOccurrences(of: "\r", with: "\\r") .replacingOccurrences(of: "\t", with: "\\t") return "\"\(escaped)\"" - }.joined(separator: ", ") + } + .joined(separator: ", ") return "[\(elements)]" } } diff --git a/Sources/SyntaxKit/ArrayLiteral.swift b/Sources/SyntaxKit/Collections/ArrayLiteral.swift similarity index 96% rename from Sources/SyntaxKit/ArrayLiteral.swift rename to Sources/SyntaxKit/Collections/ArrayLiteral.swift index e752bc1..4117858 100644 --- a/Sources/SyntaxKit/ArrayLiteral.swift +++ b/Sources/SyntaxKit/Collections/ArrayLiteral.swift @@ -29,9 +29,9 @@ import Foundation -/// An array value that can be used as a literal. +/// An array literal value that can be used as a literal. public struct ArrayLiteral: LiteralValue { - let elements: [Literal] + public let elements: [Literal] /// Creates an array with the given elements. /// - Parameter elements: The array elements. diff --git a/Sources/SyntaxKit/Dictionary+LiteralValue.swift b/Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift similarity index 98% rename from Sources/SyntaxKit/Dictionary+LiteralValue.swift rename to Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift index 980dc16..183492f 100644 --- a/Sources/SyntaxKit/Dictionary+LiteralValue.swift +++ b/Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift @@ -45,7 +45,8 @@ extension Dictionary: LiteralValue where Key == Int, Value == String { .replacingOccurrences(of: "\r", with: "\\r") .replacingOccurrences(of: "\t", with: "\\t") return "\(key): \"\(escaped)\"" - }.joined(separator: ", ") + } + .joined(separator: ", ") return "[\(elements)]" } } diff --git a/Sources/SyntaxKit/DictionaryExpr.swift b/Sources/SyntaxKit/Collections/DictionaryExpr.swift similarity index 90% rename from Sources/SyntaxKit/DictionaryExpr.swift rename to Sources/SyntaxKit/Collections/DictionaryExpr.swift index 5ff079c..0006f55 100644 --- a/Sources/SyntaxKit/DictionaryExpr.swift +++ b/Sources/SyntaxKit/Collections/DictionaryExpr.swift @@ -76,14 +76,18 @@ public struct DictionaryExpr: CodeBlock, LiteralValue { elements.enumerated().map { index, keyValue in let (key, value) = keyValue return DictionaryElementSyntax( - keyExpression: key.exprSyntax, + key: key.exprSyntax, colon: .colonToken(), - valueExpression: value.exprSyntax, - trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + value: value.exprSyntax, + trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .newline) : nil ) } ) - return DictionaryExprSyntax(content: .elements(dictionaryElements)) + return DictionaryExprSyntax( + leftSquare: .leftSquareToken(trailingTrivia: .newline), + content: .elements(dictionaryElements), + rightSquare: .rightSquareToken(leadingTrivia: .newline) + ) } } } diff --git a/Sources/SyntaxKit/DictionaryLiteral.swift b/Sources/SyntaxKit/Collections/DictionaryLiteral.swift similarity index 98% rename from Sources/SyntaxKit/DictionaryLiteral.swift rename to Sources/SyntaxKit/Collections/DictionaryLiteral.swift index c2d7de7..03dc8a8 100644 --- a/Sources/SyntaxKit/DictionaryLiteral.swift +++ b/Sources/SyntaxKit/Collections/DictionaryLiteral.swift @@ -31,7 +31,7 @@ import Foundation /// A dictionary literal value that can be used as a literal. public struct DictionaryLiteral: LiteralValue { - let elements: [(Literal, Literal)] + public let elements: [(Literal, Literal)] /// Creates a dictionary with the given key-value pairs. /// - Parameter elements: The dictionary key-value pairs. diff --git a/Sources/SyntaxKit/DictionaryValue.swift b/Sources/SyntaxKit/Collections/DictionaryValue.swift similarity index 100% rename from Sources/SyntaxKit/DictionaryValue.swift rename to Sources/SyntaxKit/Collections/DictionaryValue.swift diff --git a/Sources/SyntaxKit/Tuple.swift b/Sources/SyntaxKit/Collections/Tuple.swift similarity index 100% rename from Sources/SyntaxKit/Tuple.swift rename to Sources/SyntaxKit/Collections/Tuple.swift diff --git a/Sources/SyntaxKit/TupleAssignment+AsyncSet.swift b/Sources/SyntaxKit/Collections/TupleAssignment+AsyncSet.swift similarity index 92% rename from Sources/SyntaxKit/TupleAssignment+AsyncSet.swift rename to Sources/SyntaxKit/Collections/TupleAssignment+AsyncSet.swift index f28bd41..2606a41 100644 --- a/Sources/SyntaxKit/TupleAssignment+AsyncSet.swift +++ b/Sources/SyntaxKit/Collections/TupleAssignment+AsyncSet.swift @@ -31,7 +31,7 @@ import SwiftSyntax extension TupleAssignment { internal enum AsyncSet { - static func tuplePattern(elements: [String]) -> PatternSyntax { + internal static func tuplePattern(elements: [String]) -> PatternSyntax { let patternElements = TuplePatternElementListSyntax( elements.enumerated().map { index, element in TuplePatternElementSyntax( @@ -51,7 +51,7 @@ extension TupleAssignment { ) } - static func tupleExpr(tuple: Tuple) -> ExprSyntax { + internal static func tupleExpr(tuple: Tuple) -> ExprSyntax { ExprSyntax( TupleExprSyntax( leftParen: .leftParenToken(), @@ -71,7 +71,7 @@ extension TupleAssignment { ) } - static func valueExpr(tupleExpr: ExprSyntax, isThrowing: Bool) -> ExprSyntax { + internal static func valueExpr(tupleExpr: ExprSyntax, isThrowing: Bool) -> ExprSyntax { isThrowing ? ExprSyntax( TryExprSyntax( diff --git a/Sources/SyntaxKit/TupleAssignment.swift b/Sources/SyntaxKit/Collections/TupleAssignment.swift similarity index 98% rename from Sources/SyntaxKit/TupleAssignment.swift rename to Sources/SyntaxKit/Collections/TupleAssignment.swift index 10da5e6..7a96427 100644 --- a/Sources/SyntaxKit/TupleAssignment.swift +++ b/Sources/SyntaxKit/Collections/TupleAssignment.swift @@ -84,7 +84,8 @@ public struct TupleAssignment: CodeBlock { // Generate a single async let tuple destructuring assignment guard let tuple = value as? Tuple, elements.count == tuple.elements.count else { fatalError( - "asyncSet requires a Tuple value with the same number of elements as the assignment.") + "asyncSet requires a Tuple value with the same number of elements as the assignment." + ) } // Use helpers from AsyncSet @@ -168,7 +169,9 @@ public struct TupleAssignment: CodeBlock { private func buildValueExpression() -> ExprSyntax { let baseExpr = value.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + ?? ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier("")) + ) if isThrowing { if isAsync { diff --git a/Sources/SyntaxKit/TupleLiteral.swift b/Sources/SyntaxKit/Collections/TupleLiteral.swift similarity index 98% rename from Sources/SyntaxKit/TupleLiteral.swift rename to Sources/SyntaxKit/Collections/TupleLiteral.swift index ecf3444..4bbba1a 100644 --- a/Sources/SyntaxKit/TupleLiteral.swift +++ b/Sources/SyntaxKit/Collections/TupleLiteral.swift @@ -31,7 +31,7 @@ import Foundation /// A tuple literal value that can be used as a literal. public struct TupleLiteral: LiteralValue { - let elements: [Literal?] + public let elements: [Literal?] /// Creates a tuple with the given elements. /// - Parameter elements: The tuple elements, where `nil` represents a wildcard. diff --git a/Sources/SyntaxKit/TuplePattern.swift b/Sources/SyntaxKit/Collections/TuplePattern.swift similarity index 100% rename from Sources/SyntaxKit/TuplePattern.swift rename to Sources/SyntaxKit/Collections/TuplePattern.swift diff --git a/Sources/SyntaxKit/TuplePatternCodeBlock.swift b/Sources/SyntaxKit/Collections/TuplePatternCodeBlock.swift similarity index 100% rename from Sources/SyntaxKit/TuplePatternCodeBlock.swift rename to Sources/SyntaxKit/Collections/TuplePatternCodeBlock.swift diff --git a/Sources/SyntaxKit/Do.swift b/Sources/SyntaxKit/ControlFlow/Do.swift similarity index 100% rename from Sources/SyntaxKit/Do.swift rename to Sources/SyntaxKit/ControlFlow/Do.swift diff --git a/Sources/SyntaxKit/For.swift b/Sources/SyntaxKit/ControlFlow/For.swift similarity index 99% rename from Sources/SyntaxKit/For.swift rename to Sources/SyntaxKit/ControlFlow/For.swift index ed3c963..ff3a5d1 100644 --- a/Sources/SyntaxKit/For.swift +++ b/Sources/SyntaxKit/ControlFlow/For.swift @@ -118,7 +118,8 @@ public struct For: CodeBlock { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) diff --git a/Sources/SyntaxKit/Guard.swift b/Sources/SyntaxKit/ControlFlow/Guard.swift similarity index 100% rename from Sources/SyntaxKit/Guard.swift rename to Sources/SyntaxKit/ControlFlow/Guard.swift diff --git a/Sources/SyntaxKit/ControlFlow/If+Body.swift b/Sources/SyntaxKit/ControlFlow/If+Body.swift new file mode 100644 index 0000000..91d6525 --- /dev/null +++ b/Sources/SyntaxKit/ControlFlow/If+Body.swift @@ -0,0 +1,50 @@ +// +// If+Body.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension If { + /// Builds the body block for the if statement. + internal func buildBody() -> CodeBlockSyntax { + CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: buildBodyStatements(from: body), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + } + + /// Builds the statements for a code block from an array of CodeBlocks. + internal func buildBodyStatements(from blocks: [CodeBlock]) -> CodeBlockItemListSyntax { + CodeBlockItemListSyntax( + blocks.compactMap { block in + createCodeBlockItem(from: block)?.with(\.trailingTrivia, .newline) + } + ) + } +} diff --git a/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift b/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift new file mode 100644 index 0000000..c7c41af --- /dev/null +++ b/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift @@ -0,0 +1,47 @@ +// +// If+CodeBlockItem.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension If { + /// Creates a code block item from a CodeBlock. + internal func createCodeBlockItem(from block: CodeBlock) -> CodeBlockItemSyntax? { + if let enumCase = block as? EnumCase { + // Handle EnumCase specially - use expression syntax for enum cases in expressions + return CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)) + } else if let decl = block.syntax.as(DeclSyntax.self) { + return CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = block.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = block.syntax.as(StmtSyntax.self) { + return CodeBlockItemSyntax(item: .stmt(stmt)) + } + return nil + } +} diff --git a/Sources/SyntaxKit/ControlFlow/If+Conditions.swift b/Sources/SyntaxKit/ControlFlow/If+Conditions.swift new file mode 100644 index 0000000..61b7725 --- /dev/null +++ b/Sources/SyntaxKit/ControlFlow/If+Conditions.swift @@ -0,0 +1,92 @@ +// +// If+Conditions.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension If { + /// Builds the condition elements for the if statement. + internal func buildConditions() -> ConditionElementListSyntax { + ConditionElementListSyntax( + conditions.enumerated().map { index, block in + let needsComma = index < conditions.count - 1 + return buildConditionElement(from: block, needsComma: needsComma) + } + ) + } + + /// Builds a single condition element from a code block. + private func buildConditionElement( + from block: CodeBlock, + needsComma: Bool + ) -> ConditionElementSyntax { + let element = createConditionElement(from: block) + return appendCommaIfNeeded(element, needsComma: needsComma) + } + + /// Creates a condition element from a code block. + private func createConditionElement(from block: CodeBlock) -> ConditionElementSyntax { + if let letCond = block as? Let { + return ConditionElementSyntax( + condition: .optionalBinding( + OptionalBindingConditionSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: IdentifierPatternSyntax( + identifier: .identifier(letCond.name) + ), + initializer: InitializerClauseSyntax( + equal: .equalToken( + leadingTrivia: .space, + trailingTrivia: .space + ), + value: letCond.value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + ) + ) + ) + ) + } else { + return ConditionElementSyntax( + condition: .expression( + ExprSyntax( + fromProtocol: block.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + ) + ) + } + } + + /// Appends a comma to the condition element if needed. + private func appendCommaIfNeeded( + _ element: ConditionElementSyntax, + needsComma: Bool + ) -> ConditionElementSyntax { + needsComma ? element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) : element + } +} diff --git a/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift b/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift new file mode 100644 index 0000000..926b490 --- /dev/null +++ b/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift @@ -0,0 +1,144 @@ +// +// If+ElseBody.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension If { + /// Builds the else body for the if statement, handling else-if chains. + internal func buildElseBody() -> IfExprSyntax.ElseBody? { + guard let elseBlocks = elseBody else { + return nil + } + + // Build a chained else-if structure if the builder provided If blocks. + var current: SyntaxProtocol? + + for block in elseBlocks.reversed() { + current = processElseBlock(block, current: current) + } + + return createElseBody(from: current) + } + + /// Processes a single else block and updates the current syntax. + private func processElseBlock( + _ block: CodeBlock, + current: SyntaxProtocol? + ) -> SyntaxProtocol? { + switch block { + case let thenBlock as Then: + return buildThenBlock(thenBlock) + case let ifBlock as If: + return processIfBlock(ifBlock, current: current) + default: + return buildDefaultElseBlock(block) + } + } + + /// Builds a Then block for the else clause. + private func buildThenBlock(_ thenBlock: Then) -> SyntaxProtocol { + let stmts = CodeBlockItemListSyntax( + thenBlock.body.compactMap { element in + createCodeBlockItem(from: element)?.with(\.trailingTrivia, .newline) + } + ) + return CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: stmts, + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) as SyntaxProtocol + } + + /// Creates an else choice from a syntax protocol. + private func createElseChoice(from nested: SyntaxProtocol) -> IfExprSyntax.ElseBody { + if let codeBlock = nested.as(CodeBlockSyntax.self) { + return IfExprSyntax.ElseBody(codeBlock) + } else if let nestedIf = nested.as(IfExprSyntax.self) { + return IfExprSyntax.ElseBody(nestedIf) + } else { + // Fallback to empty code block + return IfExprSyntax.ElseBody( + CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax([]), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + ) + } + } + + /// Processes an If block to build the else-if chain. + private func processIfBlock( + _ ifBlock: If, + current: SyntaxProtocol? + ) -> SyntaxProtocol? { + guard var ifExpr = ifBlock.syntax.as(IfExprSyntax.self) else { + return current + } + + if let nested = current { + let elseChoice = createElseChoice(from: nested) + ifExpr = + ifExpr + .with(\.elseKeyword, .keyword(.else, leadingTrivia: .space, trailingTrivia: .space)) + .with(\.elseBody, elseChoice) + } + return ifExpr as SyntaxProtocol + } + + /// Builds a default else block for any other CodeBlock type. + private func buildDefaultElseBlock(_ block: CodeBlock) -> SyntaxProtocol? { + guard let item = createCodeBlockItem(from: block) else { + return nil + } + + return CodeBlockSyntax( + leftBrace: .leftBraceToken( + leadingTrivia: .space, + trailingTrivia: .newline + ), + statements: CodeBlockItemListSyntax([item.with(\.trailingTrivia, .newline)]), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + } + + /// Creates the final else body from the processed syntax. + private func createElseBody(from current: SyntaxProtocol?) -> IfExprSyntax.ElseBody? { + guard let final = current else { + return nil + } + + if let codeBlock = final.as(CodeBlockSyntax.self) { + return IfExprSyntax.ElseBody(codeBlock) + } else if let ifExpr = final.as(IfExprSyntax.self) { + return IfExprSyntax.ElseBody(ifExpr) + } + return nil + } +} diff --git a/Sources/SyntaxKit/ControlFlow/If.swift b/Sources/SyntaxKit/ControlFlow/If.swift new file mode 100644 index 0000000..65bcca7 --- /dev/null +++ b/Sources/SyntaxKit/ControlFlow/If.swift @@ -0,0 +1,86 @@ +// +// If.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// An `if` statement. +public struct If: CodeBlock { + internal let conditions: [CodeBlock] + internal let body: [CodeBlock] + internal let elseBody: [CodeBlock]? + + /// Creates an `if` statement with optional `else`. + /// - Parameters: + /// - condition: A single `CodeBlock` produced by the builder that describes the `if` condition. + /// - then: Builder that produces the body for the `if` branch. + /// - elseBody: Builder that produces the body for the `else` branch. The body may contain + /// nested `If` instances (representing `else if`) and/or a ``Then`` block for the + /// final `else` statements. + public init( + @CodeBlockBuilderResult _ condition: () -> [CodeBlock], + @CodeBlockBuilderResult then: () -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } + ) { + let allConditions = condition() + guard !allConditions.isEmpty else { + fatalError("If requires at least one condition CodeBlock") + } + self.conditions = allConditions + self.body = then() + let generatedElse = elseBody() + self.elseBody = generatedElse.isEmpty ? nil : generatedElse + } + + /// Convenience initializer that keeps the previous API: pass the condition directly. + public init( + _ condition: CodeBlock, + @CodeBlockBuilderResult then: () -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } + ) { + self.init({ condition }, then: then, else: elseBody) + } + + public var syntax: SyntaxProtocol { + // Build list of ConditionElements from all provided conditions + let condList = buildConditions() + let bodyBlock = buildBody() + let elseBlock = buildElseBody() + + return ExprSyntax( + IfExprSyntax( + ifKeyword: .keyword(.if, trailingTrivia: .space), + conditions: condList, + body: bodyBlock, + elseKeyword: elseBlock != nil + ? .keyword(.else, leadingTrivia: .space, trailingTrivia: .space) : nil, + elseBody: elseBlock + ) + ) + } +} diff --git a/Sources/SyntaxKit/Switch.swift b/Sources/SyntaxKit/ControlFlow/Switch.swift similarity index 90% rename from Sources/SyntaxKit/Switch.swift rename to Sources/SyntaxKit/ControlFlow/Switch.swift index bd44369..1def183 100644 --- a/Sources/SyntaxKit/Switch.swift +++ b/Sources/SyntaxKit/ControlFlow/Switch.swift @@ -58,9 +58,15 @@ public struct Switch: CodeBlock { ?? DeclReferenceExprSyntax(baseName: .identifier("")) ) let casesArr: [SwitchCaseSyntax] = self.cases.compactMap { - if let tupleCase = $0 as? Case { return tupleCase.switchCaseSyntax } - if let switchCase = $0 as? SwitchCase { return switchCase.switchCaseSyntax } - if let switchDefault = $0 as? Default { return switchDefault.switchCaseSyntax } + if let tupleCase = $0 as? Case { + return tupleCase.switchCaseSyntax + } + if let switchCase = $0 as? SwitchCase { + return switchCase.switchCaseSyntax + } + if let switchDefault = $0 as? Default { + return switchDefault.switchCaseSyntax + } return nil } let cases = SwitchCaseListSyntax(casesArr.map { SwitchCaseListSyntax.Element($0) }) diff --git a/Sources/SyntaxKit/SwitchCase.swift b/Sources/SyntaxKit/ControlFlow/SwitchCase.swift similarity index 95% rename from Sources/SyntaxKit/SwitchCase.swift rename to Sources/SyntaxKit/ControlFlow/SwitchCase.swift index 0b579cc..5e10279 100644 --- a/Sources/SyntaxKit/SwitchCase.swift +++ b/Sources/SyntaxKit/ControlFlow/SwitchCase.swift @@ -66,7 +66,8 @@ public struct SwitchCase: CodeBlock { } else if let variableExp = pattern as? VariableExp { // Handle VariableExp specially - convert to identifier pattern patternSyntax = PatternSyntax( - IdentifierPatternSyntax(identifier: .identifier(variableExp.name))) + IdentifierPatternSyntax(identifier: .identifier(variableExp.name)) + ) } else if let codeBlock = pattern as? CodeBlock { // Convert CodeBlock to expression pattern let expr = ExprSyntax( @@ -80,10 +81,14 @@ public struct SwitchCase: CodeBlock { var item = SwitchCaseItemSyntax(pattern: patternSyntax) if index < patterns.count - 1 { - item = item.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + item = item.with( + \.trailingComma, + .commaToken(trailingTrivia: .space) + ) } return item - }) + } + ) // Handle special case for multiple conditionals with let binding and where clause var finalCaseItems = caseItems @@ -104,7 +109,11 @@ public struct SwitchCase: CodeBlock { ) let whereClause = WhereClauseSyntax( - whereKeyword: .keyword(.where, leadingTrivia: .space, trailingTrivia: .space), + whereKeyword: .keyword( + .where, + leadingTrivia: .space, + trailingTrivia: .space + ), condition: whereExpr ) diff --git a/Sources/SyntaxKit/SwitchLet.swift b/Sources/SyntaxKit/ControlFlow/SwitchLet.swift similarity index 94% rename from Sources/SyntaxKit/SwitchLet.swift rename to Sources/SyntaxKit/ControlFlow/SwitchLet.swift index 617fa22..ec3153a 100644 --- a/Sources/SyntaxKit/SwitchLet.swift +++ b/Sources/SyntaxKit/ControlFlow/SwitchLet.swift @@ -40,12 +40,15 @@ public struct SwitchLet: PatternConvertible, CodeBlock { } public var patternSyntax: PatternSyntax { - let identifier = IdentifierPatternSyntax(identifier: .identifier(name)) + let identifier = IdentifierPatternSyntax( + identifier: .identifier(name) + ) return PatternSyntax( ValueBindingPatternSyntax( bindingSpecifier: .keyword(.let, trailingTrivia: .space), pattern: identifier - )) + ) + ) } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/While.swift b/Sources/SyntaxKit/ControlFlow/While.swift similarity index 94% rename from Sources/SyntaxKit/While.swift rename to Sources/SyntaxKit/ControlFlow/While.swift index 1d2aafc..44080be 100644 --- a/Sources/SyntaxKit/While.swift +++ b/Sources/SyntaxKit/ControlFlow/While.swift @@ -80,18 +80,21 @@ public struct While: CodeBlock { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) return StmtSyntax( WhileStmtSyntax( whileKeyword: .keyword(.while, trailingTrivia: .space), - conditions: ConditionElementListSyntax([ - ConditionElementSyntax( - condition: .expression(conditionExpr) - ) - ]), + conditions: ConditionElementListSyntax( + [ + ConditionElementSyntax( + condition: .expression(conditionExpr) + ) + ] + ), body: bodyBlock ) ) diff --git a/Sources/SyntaxKit/Core/CodeBlock.swift b/Sources/SyntaxKit/Core/CodeBlock.swift new file mode 100644 index 0000000..e6d5588 --- /dev/null +++ b/Sources/SyntaxKit/Core/CodeBlock.swift @@ -0,0 +1,37 @@ +// +// CodeBlock.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// A protocol for types that can be represented as a SwiftSyntax node. +public protocol CodeBlock { + /// The SwiftSyntax representation of the code block. + var syntax: SyntaxProtocol { get } +} diff --git a/Sources/SyntaxKit/Line.swift b/Sources/SyntaxKit/Core/Line.swift similarity index 73% rename from Sources/SyntaxKit/Line.swift rename to Sources/SyntaxKit/Core/Line.swift index 5127453..3017ae6 100644 --- a/Sources/SyntaxKit/Line.swift +++ b/Sources/SyntaxKit/Core/Line.swift @@ -27,27 +27,6 @@ // OTHER DEALINGS IN THE SOFTWARE. // -/// obtaining a copy of this software and associated documentation -/// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - import SwiftSyntax /// Represents a single comment line that can be attached to a syntax node. diff --git a/Sources/SyntaxKit/Core/PatternConvertible.swift b/Sources/SyntaxKit/Core/PatternConvertible.swift new file mode 100644 index 0000000..de8d77e --- /dev/null +++ b/Sources/SyntaxKit/Core/PatternConvertible.swift @@ -0,0 +1,37 @@ +// +// PatternConvertible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import SwiftSyntax + +/// Types that can be turned into a `PatternSyntax` suitable for a `switch` case pattern. +public protocol PatternConvertible { + /// SwiftSyntax representation of the pattern. + var patternSyntax: PatternSyntax { get } +} diff --git a/Sources/SyntaxKit/Class.swift b/Sources/SyntaxKit/Declarations/Class.swift similarity index 99% rename from Sources/SyntaxKit/Class.swift rename to Sources/SyntaxKit/Declarations/Class.swift index bf28ff4..56446f3 100644 --- a/Sources/SyntaxKit/Class.swift +++ b/Sources/SyntaxKit/Declarations/Class.swift @@ -141,7 +141,9 @@ public struct Class: CodeBlock { leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), members: MemberBlockItemListSyntax( members.compactMap { member in - guard let decl = member.syntax.as(DeclSyntax.self) else { return nil } + guard let decl = member.syntax.as(DeclSyntax.self) else { + return nil + } return MemberBlockItemSyntax(decl: decl, trailingTrivia: .newline) } ), diff --git a/Sources/SyntaxKit/Enum.swift b/Sources/SyntaxKit/Declarations/Enum.swift similarity index 97% rename from Sources/SyntaxKit/Enum.swift rename to Sources/SyntaxKit/Declarations/Enum.swift index a8c8e52..1945142 100644 --- a/Sources/SyntaxKit/Enum.swift +++ b/Sources/SyntaxKit/Declarations/Enum.swift @@ -73,7 +73,8 @@ public struct Enum: CodeBlock { if !inheritance.isEmpty { let inheritedTypes = inheritance.map { type in InheritedTypeSyntax( - type: IdentifierTypeSyntax(name: .identifier(type))) + type: IdentifierTypeSyntax(name: .identifier(type)) + ) } inheritanceClause = InheritanceClauseSyntax( colon: .colonToken(), @@ -96,9 +97,12 @@ public struct Enum: CodeBlock { leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), members: MemberBlockItemListSyntax( members.compactMap { member in - guard let syntax = member.syntax.as(DeclSyntax.self) else { return nil } + guard let syntax = member.syntax.as(DeclSyntax.self) else { + return nil + } return MemberBlockItemSyntax(decl: syntax, trailingTrivia: .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) diff --git a/Sources/SyntaxKit/Extension.swift b/Sources/SyntaxKit/Declarations/Extension.swift similarity index 98% rename from Sources/SyntaxKit/Extension.swift rename to Sources/SyntaxKit/Declarations/Extension.swift index a61f803..af53db4 100644 --- a/Sources/SyntaxKit/Extension.swift +++ b/Sources/SyntaxKit/Declarations/Extension.swift @@ -92,9 +92,12 @@ public struct Extension: CodeBlock { leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), members: MemberBlockItemListSyntax( members.compactMap { member in - guard let syntax = member.syntax.as(DeclSyntax.self) else { return nil } + guard let syntax = member.syntax.as(DeclSyntax.self) else { + return nil + } return MemberBlockItemSyntax(decl: syntax, trailingTrivia: .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) diff --git a/Sources/SyntaxKit/Init.swift b/Sources/SyntaxKit/Declarations/Init.swift similarity index 90% rename from Sources/SyntaxKit/Init.swift rename to Sources/SyntaxKit/Declarations/Init.swift index acf8122..5ef1c2c 100644 --- a/Sources/SyntaxKit/Init.swift +++ b/Sources/SyntaxKit/Declarations/Init.swift @@ -57,17 +57,24 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { return nil } if index < parameters.count - 1 { - return element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + return element.with( + \.trailingComma, + .commaToken(trailingTrivia: .space) + ) } return element - }) + } + ) return ExprSyntax( FunctionCallExprSyntax( - calledExpression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(type))), + calledExpression: ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier(type)) + ), leftParen: .leftParenToken(), arguments: args, rightParen: .rightParenToken() - )) + ) + ) } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/Protocol.swift b/Sources/SyntaxKit/Declarations/Protocol.swift similarity index 99% rename from Sources/SyntaxKit/Protocol.swift rename to Sources/SyntaxKit/Declarations/Protocol.swift index bc11002..018af73 100644 --- a/Sources/SyntaxKit/Protocol.swift +++ b/Sources/SyntaxKit/Declarations/Protocol.swift @@ -97,7 +97,9 @@ public struct Protocol: CodeBlock { leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), members: MemberBlockItemListSyntax( members.compactMap { member in - guard let decl = member.syntax.as(DeclSyntax.self) else { return nil } + guard let decl = member.syntax.as(DeclSyntax.self) else { + return nil + } return MemberBlockItemSyntax(decl: decl, trailingTrivia: .newline) } ), diff --git a/Sources/SyntaxKit/Struct.swift b/Sources/SyntaxKit/Declarations/Struct.swift similarity index 97% rename from Sources/SyntaxKit/Struct.swift rename to Sources/SyntaxKit/Declarations/Struct.swift index cbf7b76..e4dc406 100644 --- a/Sources/SyntaxKit/Struct.swift +++ b/Sources/SyntaxKit/Declarations/Struct.swift @@ -96,7 +96,8 @@ public struct Struct: CodeBlock { if !inheritance.isEmpty { let inheritedTypes = inheritance.map { type in InheritedTypeSyntax( - type: IdentifierTypeSyntax(name: .identifier(type))) + type: IdentifierTypeSyntax(name: .identifier(type)) + ) } inheritanceClause = InheritanceClauseSyntax( colon: .colonToken(), @@ -119,9 +120,12 @@ public struct Struct: CodeBlock { leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), members: MemberBlockItemListSyntax( members.compactMap { member in - guard let syntax = member.syntax.as(DeclSyntax.self) else { return nil } + guard let syntax = member.syntax.as(DeclSyntax.self) else { + return nil + } return MemberBlockItemSyntax(decl: syntax, trailingTrivia: .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) diff --git a/Sources/SyntaxKit/TypeAlias.swift b/Sources/SyntaxKit/Declarations/TypeAlias.swift similarity index 100% rename from Sources/SyntaxKit/TypeAlias.swift rename to Sources/SyntaxKit/Declarations/TypeAlias.swift diff --git a/Sources/SyntaxKit/Catch.swift b/Sources/SyntaxKit/ErrorHandling/Catch.swift similarity index 99% rename from Sources/SyntaxKit/Catch.swift rename to Sources/SyntaxKit/ErrorHandling/Catch.swift index a4db19a..edad97f 100644 --- a/Sources/SyntaxKit/Catch.swift +++ b/Sources/SyntaxKit/ErrorHandling/Catch.swift @@ -181,7 +181,8 @@ public struct Catch: CodeBlock { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline, trailingTrivia: .space) ) diff --git a/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift b/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift new file mode 100644 index 0000000..0e05237 --- /dev/null +++ b/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift @@ -0,0 +1,157 @@ +// +// CatchBuilder.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A result builder for creating catch clauses in a do-catch statement. +/// +/// `CatchBuilder` enables the creation of multiple catch clauses using Swift's result builder syntax. +/// It's used in conjunction with the ``Do`` struct to build comprehensive error handling blocks. +/// +/// ## Overview +/// +/// The `CatchBuilder` implements the result builder pattern to allow for declarative construction +/// of catch clauses. It supports various catch clause types including: +/// - Pattern-based catch clauses (e.g., `catch .specificError`) +/// - Catch clauses with associated values (e.g., `catch .error(let code, let message)`) +/// - General catch clauses (e.g., `catch`) +/// +/// ## Usage +/// +/// ```swift +/// Do { +/// // Code that may throw +/// try someFunction() +/// } catch: { +/// Catch(EnumCase("networkError")) { +/// Call("handleNetworkError")() +/// } +/// Catch(EnumCase("validationError").associatedValue("field", type: "String")) { +/// Call("handleValidationError") { +/// ParameterExp(name: "field", value: VariableExp("field")) +/// } +/// } +/// Catch { +/// Call("handleGenericError")() +/// } +/// } +/// ``` +/// +/// ## Result Builder Methods +/// +/// The builder provides several methods that implement the result builder protocol: +/// - `buildBlock`: Combines multiple catch clauses into a list +/// - `buildExpression`: Converts individual catch expressions +/// - `buildOptional`: Handles optional catch clauses +/// - `buildEither`: Supports conditional catch clauses +/// - `buildArray`: Handles array-based catch clause construction +/// +/// ## Integration with SwiftSyntax +/// +/// The builder produces `CatchClauseListSyntax` which is directly compatible with SwiftSyntax's +/// `DoStmtSyntax`, enabling seamless integration with the Swift compiler's syntax tree. +@resultBuilder +public enum CatchBuilder { + /// Combines multiple catch clauses into a `CatchClauseListSyntax`. + /// + /// This method is called by the result builder when multiple catch clauses are provided + /// in the catch block. It creates a list of catch clauses that can be attached to a do statement. + /// + /// - Parameter components: The catch clauses to combine. + /// - Returns: A `CatchClauseListSyntax` containing all the provided catch clauses. + public static func buildBlock(_ components: CatchClauseSyntax...) -> CatchClauseListSyntax { + CatchClauseListSyntax(components) + } + + /// Converts a `CatchClauseSyntax` expression into a catch clause. + /// + /// This method handles direct `CatchClauseSyntax` instances, allowing for custom + /// catch clause construction when needed. + /// + /// - Parameter expression: The catch clause syntax to convert. + /// - Returns: The same catch clause syntax. + public static func buildExpression(_ expression: CatchClauseSyntax) -> CatchClauseSyntax { + expression + } + + /// Converts a ``Catch`` instance into a `CatchClauseSyntax`. + /// + /// This method handles ``Catch`` struct instances, converting them into the appropriate + /// syntax representation. This is the most common use case when working with the DSL. + /// + /// - Parameter expression: The `Catch` instance to convert. + /// - Returns: A `CatchClauseSyntax` representing the catch clause. + public static func buildExpression(_ expression: Catch) -> CatchClauseSyntax { + expression.catchClauseSyntax + } + + /// Handles optional catch clauses in conditional contexts. + /// + /// This method supports conditional catch clause construction, allowing for + /// catch clauses that may or may not be included based on runtime conditions. + /// + /// - Parameter component: An optional catch clause. + /// - Returns: The optional catch clause, unchanged. + public static func buildOptional(_ component: CatchClauseSyntax?) -> CatchClauseSyntax? { + component + } + + /// Handles the first branch of a conditional catch clause. + /// + /// This method supports `if-else` constructs within catch blocks, allowing for + /// conditional error handling logic. + /// + /// - Parameter component: The catch clause for the first branch. + /// - Returns: The catch clause syntax. + public static func buildEither(first component: CatchClauseSyntax) -> CatchClauseSyntax { + component + } + + /// Handles the second branch of a conditional catch clause. + /// + /// This method supports `if-else` constructs within catch blocks, allowing for + /// conditional error handling logic. + /// + /// - Parameter component: The catch clause for the second branch. + /// - Returns: The catch clause syntax. + public static func buildEither(second component: CatchClauseSyntax) -> CatchClauseSyntax { + component + } + + /// Combines an array of catch clauses into a `CatchClauseListSyntax`. + /// + /// This method supports array-based catch clause construction, useful for + /// dynamic catch clause generation or when working with collections of catch patterns. + /// + /// - Parameter components: An array of catch clauses to combine. + /// - Returns: A `CatchClauseListSyntax` containing all the catch clauses. + public static func buildArray(_ components: [CatchClauseSyntax]) -> CatchClauseListSyntax { + CatchClauseListSyntax(components) + } +} diff --git a/Sources/SyntaxKit/Throw.swift b/Sources/SyntaxKit/ErrorHandling/Throw.swift similarity index 100% rename from Sources/SyntaxKit/Throw.swift rename to Sources/SyntaxKit/ErrorHandling/Throw.swift diff --git a/Sources/SyntaxKit/Assignment.swift b/Sources/SyntaxKit/Expressions/Assignment.swift similarity index 100% rename from Sources/SyntaxKit/Assignment.swift rename to Sources/SyntaxKit/Expressions/Assignment.swift diff --git a/Sources/SyntaxKit/Call.swift b/Sources/SyntaxKit/Expressions/Call.swift similarity index 91% rename from Sources/SyntaxKit/Call.swift rename to Sources/SyntaxKit/Expressions/Call.swift index f3df787..a72843f 100644 --- a/Sources/SyntaxKit/Call.swift +++ b/Sources/SyntaxKit/Expressions/Call.swift @@ -76,7 +76,10 @@ public struct Call: CodeBlock { if let labeled = expr as? LabeledExprSyntax { var element = labeled if index < parameters.count - 1 { - element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + element = element.with( + \.trailingComma, + .commaToken(trailingTrivia: .space) + ) } return element } else if let unlabeled = expr as? ExprSyntax { @@ -84,15 +87,20 @@ public struct Call: CodeBlock { label: nil, colon: nil, expression: unlabeled, - trailingComma: index < parameters.count - 1 ? .commaToken(trailingTrivia: .space) : nil + trailingComma: index < parameters.count - 1 + ? .commaToken(trailingTrivia: .space) + : nil ) } else { fatalError("ParameterExp.syntax must return LabeledExprSyntax or ExprSyntax") } - }) + } + ) let functionCall = FunctionCallExprSyntax( - calledExpression: ExprSyntax(DeclReferenceExprSyntax(baseName: function)), + calledExpression: ExprSyntax( + DeclReferenceExprSyntax(baseName: function) + ), leftParen: .leftParenToken(), arguments: args, rightParen: .rightParenToken() diff --git a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift new file mode 100644 index 0000000..e30e5d5 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift @@ -0,0 +1,103 @@ +// +// FunctionCallExp.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// An expression that calls a function. +public struct FunctionCallExp: CodeBlock { + internal let baseName: String + internal let methodName: String + internal let parameters: [ParameterExp] + + /// Creates a function call expression. + /// - Parameters: + /// - baseName: The name of the base variable. + /// - methodName: The name of the method to call. + public init(baseName: String, methodName: String) { + self.baseName = baseName + self.methodName = methodName + self.parameters = [] + } + + /// Creates a function call expression with parameters. + /// - Parameters: + /// - baseName: The name of the base variable. + /// - methodName: The name of the method to call. + /// - parameters: The parameters for the method call. + public init(baseName: String, methodName: String, parameters: [ParameterExp]) { + self.baseName = baseName + self.methodName = methodName + self.parameters = parameters + } + + public var syntax: SyntaxProtocol { + let base = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(baseName))) + let method = TokenSyntax.identifier(methodName) + let args = LabeledExprListSyntax( + parameters.enumerated().map { index, param in + let expr = param.syntax + if let labeled = expr as? LabeledExprSyntax { + var element = labeled + if index < parameters.count - 1 { + element = element.with( + \.trailingComma, + .commaToken(trailingTrivia: .space) + ) + } + return element + } else if let unlabeled = expr as? ExprSyntax { + return TupleExprElementSyntax( + label: nil, + colon: nil, + expression: unlabeled, + trailingComma: index < parameters.count - 1 + ? .commaToken(trailingTrivia: .space) + : nil + ) + } else { + fatalError("ParameterExp.syntax must return LabeledExprSyntax or ExprSyntax") + } + } + ) + return ExprSyntax( + FunctionCallExprSyntax( + calledExpression: ExprSyntax( + MemberAccessExprSyntax( + base: base, + dot: .periodToken(), + name: method + ) + ), + leftParen: .leftParenToken(), + arguments: args, + rightParen: .rightParenToken() + ) + ) + } +} diff --git a/Sources/SyntaxKit/Infix.swift b/Sources/SyntaxKit/Expressions/Infix.swift similarity index 56% rename from Sources/SyntaxKit/Infix.swift rename to Sources/SyntaxKit/Expressions/Infix.swift index 82ce259..432f82f 100644 --- a/Sources/SyntaxKit/Infix.swift +++ b/Sources/SyntaxKit/Expressions/Infix.swift @@ -31,17 +31,17 @@ import SwiftSyntax /// A generic binary (infix) operator expression, e.g. `a + b`. public struct Infix: CodeBlock { - private let op: String + private let operation: String private let operands: [CodeBlock] /// Creates an infix operator expression. /// - Parameters: - /// - op: The operator symbol as it should appear in source (e.g. "+", "-", "&&"). + /// - operation: The operator symbol as it should appear in source (e.g. "+", "-", "&&"). /// - content: A ``CodeBlockBuilder`` that supplies the two operand expressions. /// /// Exactly two operands must be supplied – a left-hand side and a right-hand side. - public init(_ op: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.op = op + public init(_ operation: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.operation = operation self.operands = content() } @@ -55,7 +55,7 @@ public struct Infix: CodeBlock { let operatorExpr = ExprSyntax( BinaryOperatorExprSyntax( - operator: .binaryOperator(op, leadingTrivia: .space, trailingTrivia: .space) + operator: .binaryOperator(operation, leadingTrivia: .space, trailingTrivia: .space) ) ) @@ -69,52 +69,29 @@ public struct Infix: CodeBlock { } } -// MARK: - Operator Overloads for Infix Expressions +// MARK: - Comparison Operators -/// Creates a greater-than comparison expression. -/// - Parameters: -/// - lhs: The left-hand side expression. -/// - rhs: The right-hand side expression. -/// - Returns: An infix expression representing `lhs > rhs`. -public func > (lhs: CodeBlock, rhs: CodeBlock) -> Infix { - Infix(">") { - lhs - rhs - } -} - -/// Creates a less-than comparison expression. -/// - Parameters: -/// - lhs: The left-hand side expression. -/// - rhs: The right-hand side expression. -/// - Returns: An infix expression representing `lhs < rhs`. -public func < (lhs: CodeBlock, rhs: CodeBlock) -> Infix { - Infix("<") { - lhs - rhs - } -} +extension Infix { + /// Comparison operators that can be used in infix expressions. + public enum ComparisonOperator: String, CaseIterable { + case greaterThan = ">" + case lessThan = "<" + case equal = "==" + case notEqual = "!=" -/// Creates an equality comparison expression. -/// - Parameters: -/// - lhs: The left-hand side expression. -/// - rhs: The right-hand side expression. -/// - Returns: An infix expression representing `lhs == rhs`. -public func == (lhs: CodeBlock, rhs: CodeBlock) -> Infix { - Infix("==") { - lhs - rhs + /// The string representation of the operator. + public var symbol: String { + rawValue + } } -} -/// Creates an inequality comparison expression. -/// - Parameters: -/// - lhs: The left-hand side expression. -/// - rhs: The right-hand side expression. -/// - Returns: An infix expression representing `lhs != rhs`. -public func != (lhs: CodeBlock, rhs: CodeBlock) -> Infix { - Infix("!=") { - lhs - rhs + /// Creates an infix expression with a comparison operator. + /// - Parameters: + /// - operator: The comparison operator to use. + /// - lhs: The left-hand side expression. + /// - rhs: The right-hand side expression. + public init(_ operator: ComparisonOperator, lhs: CodeBlock, rhs: CodeBlock) { + self.operation = `operator`.symbol + self.operands = [lhs, rhs] } } diff --git a/Sources/SyntaxKit/Literal+Convenience.swift b/Sources/SyntaxKit/Expressions/Literal+Convenience.swift similarity index 100% rename from Sources/SyntaxKit/Literal+Convenience.swift rename to Sources/SyntaxKit/Expressions/Literal+Convenience.swift diff --git a/Sources/SyntaxKit/Literal+ExprCodeBlock.swift b/Sources/SyntaxKit/Expressions/Literal+ExprCodeBlock.swift similarity index 77% rename from Sources/SyntaxKit/Literal+ExprCodeBlock.swift rename to Sources/SyntaxKit/Expressions/Literal+ExprCodeBlock.swift index 8b74e74..8dca1b8 100644 --- a/Sources/SyntaxKit/Literal+ExprCodeBlock.swift +++ b/Sources/SyntaxKit/Expressions/Literal+ExprCodeBlock.swift @@ -39,11 +39,14 @@ extension Literal: ExprCodeBlock { return ExprSyntax( StringLiteralExprSyntax( openingQuote: .stringQuoteToken(), - segments: .init([ - .stringSegment(.init(content: .stringSegment(value))) - ]), + segments: .init( + [ + .stringSegment(.init(content: .stringSegment(value))) + ] + ), closingQuote: .stringQuoteToken() - )) + ) + ) case .float(let value): return ExprSyntax(FloatLiteralExprSyntax(literal: .floatLiteral(String(value)))) case .integer(let value): @@ -52,7 +55,10 @@ extension Literal: ExprCodeBlock { return ExprSyntax(NilLiteralExprSyntax(nilKeyword: .keyword(.nil))) case .boolean(let value): return ExprSyntax( - BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false))) + BooleanLiteralExprSyntax( + literal: value ? .keyword(.true) : .keyword(.false) + ) + ) case .ref(let value): return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) case .tuple(let elements): @@ -69,7 +75,9 @@ extension Literal: ExprCodeBlock { label: nil, colon: nil, expression: elementExpr, - trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + trailingComma: index < elements.count - 1 + ? .commaToken(trailingTrivia: .space) + : nil ) } ) @@ -78,14 +86,19 @@ extension Literal: ExprCodeBlock { leftParen: .leftParenToken(), elements: tupleElements, rightParen: .rightParenToken() - )) + ) + ) case .array(let elements): let arrayElements = ArrayElementListSyntax( elements.enumerated().map { index, element in ArrayElementSyntax( expression: element.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))), - trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + ?? ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier("")) + ), + trailingComma: index < elements.count - 1 + ? .commaToken(trailingTrivia: .space) + : nil ) } ) @@ -96,9 +109,15 @@ extension Literal: ExprCodeBlock { return ExprSyntax( DictionaryExprSyntax( leftSquare: .leftSquareToken(), - content: .colon(.colonToken(leadingTrivia: .init(), trailingTrivia: .init())), + content: .colon( + .colonToken( + leadingTrivia: .init(), + trailingTrivia: .init() + ) + ), rightSquare: .rightSquareToken() - )) + ) + ) } else { let dictionaryElements = DictionaryElementListSyntax( elements.enumerated().map { index, keyValue in @@ -107,11 +126,17 @@ extension Literal: ExprCodeBlock { keyExpression: key.exprSyntax, colon: .colonToken(), valueExpression: value.exprSyntax, - trailingComma: index < elements.count - 1 ? .commaToken(trailingTrivia: .space) : nil + trailingComma: index < elements.count - 1 + ? .commaToken(trailingTrivia: .space) + : nil ) } ) - return ExprSyntax(DictionaryExprSyntax(content: .elements(dictionaryElements))) + return ExprSyntax( + DictionaryExprSyntax( + content: .elements(dictionaryElements) + ) + ) } } } diff --git a/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift b/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift new file mode 100644 index 0000000..39b85fc --- /dev/null +++ b/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift @@ -0,0 +1,40 @@ +// +// Literal+PatternConvertible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Literal: PatternConvertible { + /// SwiftSyntax representation of the literal as a pattern. + public var patternSyntax: PatternSyntax { + guard let expr = self.syntax.as(ExprSyntax.self) else { + fatalError("Literal.syntax did not return ExprSyntax") + } + return PatternSyntax(ExpressionPatternSyntax(expression: expr)) + } +} diff --git a/Sources/SyntaxKit/Literal.swift b/Sources/SyntaxKit/Expressions/Literal.swift similarity index 100% rename from Sources/SyntaxKit/Literal.swift rename to Sources/SyntaxKit/Expressions/Literal.swift diff --git a/Sources/SyntaxKit/LiteralValue.swift b/Sources/SyntaxKit/Expressions/LiteralValue.swift similarity index 100% rename from Sources/SyntaxKit/LiteralValue.swift rename to Sources/SyntaxKit/Expressions/LiteralValue.swift diff --git a/Sources/SyntaxKit/CatchBuilder.swift b/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift similarity index 56% rename from Sources/SyntaxKit/CatchBuilder.swift rename to Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift index 6991d2a..7b9e1c2 100644 --- a/Sources/SyntaxKit/CatchBuilder.swift +++ b/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift @@ -1,5 +1,5 @@ // -// CatchBuilder.swift +// NegatedPropertyAccessExp.swift // SyntaxKit // // Created by Leo Dion. @@ -29,34 +29,36 @@ import SwiftSyntax -/// A result builder for creating catch clauses in a do-catch statement. -@resultBuilder -public struct CatchBuilder { - public static func buildBlock(_ components: CatchClauseSyntax...) -> CatchClauseListSyntax { - CatchClauseListSyntax(components) - } - - public static func buildExpression(_ expression: CatchClauseSyntax) -> CatchClauseSyntax { - expression - } - - public static func buildExpression(_ expression: Catch) -> CatchClauseSyntax { - expression.catchClauseSyntax - } - - public static func buildOptional(_ component: CatchClauseSyntax?) -> CatchClauseSyntax? { - component - } +/// An expression that negates a property access. +public struct NegatedPropertyAccessExp: CodeBlock { + internal let base: CodeBlock - public static func buildEither(first component: CatchClauseSyntax) -> CatchClauseSyntax { - component + /// Creates a negated property access expression. + /// - Parameter base: The base property access expression. + public init(base: CodeBlock) { + self.base = base } - public static func buildEither(second component: CatchClauseSyntax) -> CatchClauseSyntax { - component + /// Backward compatibility initializer for (baseName, propertyName). + public init(baseName: String, propertyName: String) { + self.base = PropertyAccessExp(baseName: baseName, propertyName: propertyName) } - public static func buildArray(_ components: [CatchClauseSyntax]) -> CatchClauseListSyntax { - CatchClauseListSyntax(components) + public var syntax: SyntaxProtocol { + let memberAccess = + base.syntax.as(ExprSyntax.self) + ?? ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier("")) + ) + return ExprSyntax( + PrefixOperatorExprSyntax( + operator: .prefixOperator( + "!", + leadingTrivia: [], + trailingTrivia: [] + ), + expression: memberAccess + ) + ) } } diff --git a/Sources/SyntaxKit/PlusAssign.swift b/Sources/SyntaxKit/Expressions/PlusAssign.swift similarity index 94% rename from Sources/SyntaxKit/PlusAssign.swift rename to Sources/SyntaxKit/Expressions/PlusAssign.swift index 2ad0bab..7c978e7 100644 --- a/Sources/SyntaxKit/PlusAssign.swift +++ b/Sources/SyntaxKit/Expressions/PlusAssign.swift @@ -67,7 +67,13 @@ public struct PlusAssign: CodeBlock { let left = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(target))) let assign = ExprSyntax( BinaryOperatorExprSyntax( - operator: .binaryOperator("+=", leadingTrivia: .space, trailingTrivia: .space))) + operator: .binaryOperator( + "+=", + leadingTrivia: .space, + trailingTrivia: .space + ) + ) + ) return SequenceExprSyntax( elements: ExprListSyntax([ left, diff --git a/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift b/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift new file mode 100644 index 0000000..a23b53f --- /dev/null +++ b/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift @@ -0,0 +1,80 @@ +// +// PropertyAccessExp.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// An expression that accesses a property on a base expression. +public struct PropertyAccessExp: CodeBlock { + internal let base: CodeBlock + internal let propertyName: String + + /// Creates a property access expression. + /// - Parameters: + /// - base: The base expression. + /// - propertyName: The name of the property to access. + public init(base: CodeBlock, propertyName: String) { + self.base = base + self.propertyName = propertyName + } + + /// Convenience initializer for backward compatibility (baseName as String). + public init(baseName: String, propertyName: String) { + self.base = VariableExp(baseName) + self.propertyName = propertyName + } + + /// Accesses a property on the current property access expression (chaining). + /// - Parameter propertyName: The name of the next property to access. + /// - Returns: A new ``PropertyAccessExp`` representing the chained property access. + public func property(_ propertyName: String) -> PropertyAccessExp { + PropertyAccessExp(base: self, propertyName: propertyName) + } + + /// Negates the property access expression. + /// - Returns: A negated property access expression. + public func not() -> CodeBlock { + NegatedPropertyAccessExp(base: self) + } + + public var syntax: SyntaxProtocol { + let baseSyntax = + base.syntax.as(ExprSyntax.self) + ?? ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier("")) + ) + let property = TokenSyntax.identifier(propertyName) + return ExprSyntax( + MemberAccessExprSyntax( + base: baseSyntax, + dot: .periodToken(), + name: property + ) + ) + } +} diff --git a/Sources/SyntaxKit/Return.swift b/Sources/SyntaxKit/Expressions/Return.swift similarity index 100% rename from Sources/SyntaxKit/Return.swift rename to Sources/SyntaxKit/Expressions/Return.swift diff --git a/Sources/SyntaxKit/Function+EffectSpecifiers.swift b/Sources/SyntaxKit/Functions/Function+EffectSpecifiers.swift similarity index 96% rename from Sources/SyntaxKit/Function+EffectSpecifiers.swift rename to Sources/SyntaxKit/Functions/Function+EffectSpecifiers.swift index f985770..0c31748 100644 --- a/Sources/SyntaxKit/Function+EffectSpecifiers.swift +++ b/Sources/SyntaxKit/Functions/Function+EffectSpecifiers.swift @@ -35,7 +35,7 @@ extension Function { switch effect { case .none: return nil - case .throws(let isRethrows, let errorType): + case let .throws(isRethrows, errorType): let throwsSpecifier = buildThrowsSpecifier(isRethrows: isRethrows) if let errorType = errorType { return FunctionEffectSpecifiersSyntax( @@ -53,7 +53,7 @@ extension Function { asyncSpecifier: .keyword(.async, leadingTrivia: .space, trailingTrivia: .space), throwsSpecifier: nil ) - case .asyncThrows(let isRethrows, let errorType): + case let .asyncThrows(isRethrows, errorType): let throwsSpecifier = buildThrowsSpecifier(isRethrows: isRethrows) if let errorType = errorType { return FunctionEffectSpecifiersSyntax( diff --git a/Sources/SyntaxKit/Function+Effects.swift b/Sources/SyntaxKit/Functions/Function+Effects.swift similarity index 100% rename from Sources/SyntaxKit/Function+Effects.swift rename to Sources/SyntaxKit/Functions/Function+Effects.swift diff --git a/Sources/SyntaxKit/Function+Modifiers.swift b/Sources/SyntaxKit/Functions/Function+Modifiers.swift similarity index 100% rename from Sources/SyntaxKit/Function+Modifiers.swift rename to Sources/SyntaxKit/Functions/Function+Modifiers.swift diff --git a/Sources/SyntaxKit/Function+Syntax.swift b/Sources/SyntaxKit/Functions/Function+Syntax.swift similarity index 70% rename from Sources/SyntaxKit/Function+Syntax.swift rename to Sources/SyntaxKit/Functions/Function+Syntax.swift index 5c03603..8bb8796 100644 --- a/Sources/SyntaxKit/Function+Syntax.swift +++ b/Sources/SyntaxKit/Functions/Function+Syntax.swift @@ -37,50 +37,18 @@ extension Function { // Build parameter list let paramList = FunctionParameterListSyntax( - parameters.enumerated().compactMap { index, param in - // Skip empty placeholders (possible in some builder scenarios) - guard !param.name.isEmpty || param.defaultValue != nil else { return nil } - - // Attributes for parameter - let paramAttributes = buildAttributeList(from: param.attributes) - - let firstNameLeading: Trivia = paramAttributes.isEmpty ? [] : .space - - // Determine first & second names - let firstNameToken: TokenSyntax - let secondNameToken: TokenSyntax? - - if param.isUnnamed { - firstNameToken = .wildcardToken(leadingTrivia: firstNameLeading, trailingTrivia: .space) - secondNameToken = .identifier(param.name) - } else if let label = param.label { - firstNameToken = .identifier( - label, leadingTrivia: firstNameLeading, trailingTrivia: .space) - secondNameToken = .identifier(param.name) - } else { - firstNameToken = .identifier( - param.name, leadingTrivia: firstNameLeading, trailingTrivia: .space) - secondNameToken = nil - } - - var paramSyntax = FunctionParameterSyntax( - attributes: paramAttributes, - firstName: firstNameToken, - secondName: secondNameToken, - colon: .colonToken(trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(param.type)), - defaultValue: param.defaultValue.map { - InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier($0))) - ) - } - ) - if index < parameters.count - 1 { - paramSyntax = paramSyntax.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + parameters + .enumerated() + .compactMap { index, param in + let isLast = index >= parameters.count - 1 + let paramAttributes = buildAttributeList(from: param.attributes) + return FunctionParameterSyntax.create( + from: param, + attributes: paramAttributes, + isLast: isLast + ) } - return paramSyntax - }) + ) // Build return type if specified var returnClause: ReturnClauseSyntax? @@ -105,7 +73,8 @@ extension Function { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - }), + } + ), rightBrace: .rightBraceToken(leadingTrivia: .newline) ) @@ -115,15 +84,18 @@ extension Function { // Build modifiers var modifiers: DeclModifierListSyntax = [] if isStatic { - modifiers = DeclModifierListSyntax([ - DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) - ]) + modifiers = DeclModifierListSyntax( + [ + DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) + ] + ) } if isMutating { modifiers = DeclModifierListSyntax( modifiers + [ DeclModifierSyntax(name: .keyword(.mutating, trailingTrivia: .space)) - ]) + ] + ) } return FunctionDeclSyntax( @@ -171,7 +143,10 @@ extension Function { argumentList.enumerated().map { index, expr in var element = LabeledExprSyntax(expression: ExprSyntax(expr)) if index < argumentList.count - 1 { - element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + element = element.with( + \.trailingComma, + .commaToken(trailingTrivia: .space) + ) } return element } diff --git a/Sources/SyntaxKit/Function.swift b/Sources/SyntaxKit/Functions/Function.swift similarity index 96% rename from Sources/SyntaxKit/Function.swift rename to Sources/SyntaxKit/Functions/Function.swift index 655970b..038eb09 100644 --- a/Sources/SyntaxKit/Function.swift +++ b/Sources/SyntaxKit/Functions/Function.swift @@ -46,7 +46,8 @@ public struct Function: CodeBlock { /// - returnType: The return type of the function, if any. /// - content: A ``CodeBlockBuilder`` that provides the body of the function. public init( - _ name: String, returns returnType: String? = nil, + _ name: String, + returns returnType: String? = nil, @CodeBlockBuilderResult _ content: () -> [CodeBlock] ) { self.name = name @@ -62,7 +63,8 @@ public struct Function: CodeBlock { /// - params: A ``ParameterBuilder`` that provides the parameters of the function. /// - content: A ``CodeBlockBuilder`` that provides the body of the function. public init( - _ name: String, returns returnType: String? = nil, + _ name: String, + returns returnType: String? = nil, @ParameterBuilderResult _ params: () -> [Parameter], @CodeBlockBuilderResult _ content: () -> [CodeBlock] ) { diff --git a/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift b/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift new file mode 100644 index 0000000..3289a17 --- /dev/null +++ b/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift @@ -0,0 +1,114 @@ +// +// FunctionParameterSyntax+Init.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension FunctionParameterSyntax { + /// Private struct to hold parameter name tokens. + private struct ParameterNames { + let firstNameToken: TokenSyntax + let secondNameToken: TokenSyntax? + + /// Creates parameter name tokens from a parameter. + /// - Parameters: + /// - parameter: The parameter to create tokens for. + /// - firstNameLeading: The leading trivia for the first name token. + init(from parameter: Parameter, firstNameLeading: Trivia) { + if parameter.isUnnamed { + self.firstNameToken = .wildcardToken( + leadingTrivia: firstNameLeading, + trailingTrivia: .space + ) + self.secondNameToken = .identifier(parameter.name) + } else if let label = parameter.label { + self.firstNameToken = .identifier( + label, + leadingTrivia: firstNameLeading, + trailingTrivia: .space + ) + self.secondNameToken = .identifier(parameter.name) + } else { + self.firstNameToken = .identifier( + parameter.name, + leadingTrivia: firstNameLeading, + trailingTrivia: .space + ) + self.secondNameToken = nil + } + } + } + + /// Creates a `FunctionParameterSyntax` from a `Parameter`. + /// - Parameters: + /// - parameter: The parameter to convert. + /// - attributes: The attributes for the parameter. + /// - isLast: Whether this is the last parameter in the list. + /// - Returns: A `FunctionParameterSyntax` if the conversion is successful, `nil` otherwise. + public static func create( + from parameter: Parameter, + attributes: AttributeListSyntax, + isLast: Bool + ) -> FunctionParameterSyntax? { + // Skip empty placeholders (possible in some builder scenarios) + guard !parameter.name.isEmpty || parameter.defaultValue != nil else { + return nil + } + + let firstNameLeading: Trivia = attributes.isEmpty ? [] : .space + let parameterNames = ParameterNames(from: parameter, firstNameLeading: firstNameLeading) + + var paramSyntax = FunctionParameterSyntax( + attributes: attributes, + firstName: parameterNames.firstNameToken, + secondName: parameterNames.secondNameToken, + colon: .colonToken(trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(parameter.type)), + defaultValue: parameter.defaultValue.map { + InitializerClauseSyntax( + equal: .equalToken( + leadingTrivia: .space, + trailingTrivia: .space + ), + value: ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier($0)) + ) + ) + } + ) + + if !isLast { + paramSyntax = paramSyntax.with( + \.trailingComma, + .commaToken(trailingTrivia: .space) + ) + } + + return paramSyntax + } +} diff --git a/Sources/SyntaxKit/FunctionRequirement.swift b/Sources/SyntaxKit/Functions/FunctionRequirement.swift similarity index 96% rename from Sources/SyntaxKit/FunctionRequirement.swift rename to Sources/SyntaxKit/Functions/FunctionRequirement.swift index 3faf7ae..6609a9c 100644 --- a/Sources/SyntaxKit/FunctionRequirement.swift +++ b/Sources/SyntaxKit/Functions/FunctionRequirement.swift @@ -53,7 +53,8 @@ public struct FunctionRequirement: CodeBlock { /// - returnType: Optional return type. /// - params: A ParameterBuilderResult providing the parameters. public init( - _ name: String, returns returnType: String? = nil, + _ name: String, + returns returnType: String? = nil, @ParameterBuilderResult _ params: () -> [Parameter] ) { self.name = name @@ -86,7 +87,9 @@ public struct FunctionRequirement: CodeBlock { } else { paramList = FunctionParameterListSyntax( parameters.enumerated().compactMap { index, param in - guard !param.name.isEmpty, !param.type.isEmpty else { return nil } + guard !param.name.isEmpty, !param.type.isEmpty else { + return nil + } var paramSyntax = FunctionParameterSyntax( firstName: param.isUnnamed ? .wildcardToken(trailingTrivia: .space) : .identifier(param.name), @@ -104,7 +107,8 @@ public struct FunctionRequirement: CodeBlock { paramSyntax = paramSyntax.with(\.trailingComma, .commaToken(trailingTrivia: .space)) } return paramSyntax - }) + } + ) } // Return clause diff --git a/Sources/SyntaxKit/If.swift b/Sources/SyntaxKit/If.swift deleted file mode 100644 index b916df7..0000000 --- a/Sources/SyntaxKit/If.swift +++ /dev/null @@ -1,224 +0,0 @@ -// -// If.swift -// SyntaxKit -// -// Created by Leo Dion. -// Copyright © 2025 BrightDigit. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -import SwiftSyntax - -/// An `if` statement. -public struct If: CodeBlock { - private let conditions: [CodeBlock] - private let body: [CodeBlock] - private let elseBody: [CodeBlock]? - - /// Creates an `if` statement with optional `else`. - /// - Parameters: - /// - condition: A single `CodeBlock` produced by the builder that describes the `if` condition. - /// - then: Builder that produces the body for the `if` branch. - /// - elseBody: Builder that produces the body for the `else` branch. The body may contain - /// nested `If` instances (representing `else if`) and/or a ``Then`` block for the - /// final `else` statements. - public init( - @CodeBlockBuilderResult _ condition: () -> [CodeBlock], - @CodeBlockBuilderResult then: () -> [CodeBlock], - @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } - ) { - let allConditions = condition() - guard !allConditions.isEmpty else { - fatalError("If requires at least one condition CodeBlock") - } - self.conditions = allConditions - self.body = then() - let generatedElse = elseBody() - self.elseBody = generatedElse.isEmpty ? nil : generatedElse - } - - /// Convenience initializer that keeps the previous API: pass the condition directly. - public init( - _ condition: CodeBlock, - @CodeBlockBuilderResult then: () -> [CodeBlock], - @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } - ) { - self.init({ condition }, then: then, else: elseBody) - } - - public var syntax: SyntaxProtocol { - // Build list of ConditionElements from all provided conditions - let condList = ConditionElementListSyntax( - conditions.enumerated().map { index, block in - let needsComma = index < conditions.count - 1 - - func appendComma(_ element: ConditionElementSyntax) -> ConditionElementSyntax { - needsComma ? element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) : element - } - - if let letCond = block as? Let { - let element = ConditionElementSyntax( - condition: .optionalBinding( - OptionalBindingConditionSyntax( - bindingSpecifier: .keyword(.let, trailingTrivia: .space), - pattern: IdentifierPatternSyntax(identifier: .identifier(letCond.name)), - initializer: InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: letCond.value.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) - ) - ) - ) - ) - return appendComma(element) - } else { - let element = ConditionElementSyntax( - condition: .expression( - ExprSyntax( - fromProtocol: block.syntax.as(ExprSyntax.self) - ?? DeclReferenceExprSyntax(baseName: .identifier("")))) - ) - return appendComma(element) - } - } - ) - let bodyBlock = CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - statements: CodeBlockItemListSyntax( - body.compactMap { - var item: CodeBlockItemSyntax? - if let enumCase = $0 as? EnumCase { - // Handle EnumCase specially - use expression syntax for enum cases in expressions - item = CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)) - } else if let decl = $0.syntax.as(DeclSyntax.self) { - item = CodeBlockItemSyntax(item: .decl(decl)) - } else if let expr = $0.syntax.as(ExprSyntax.self) { - item = CodeBlockItemSyntax(item: .expr(expr)) - } else if let stmt = $0.syntax.as(StmtSyntax.self) { - item = CodeBlockItemSyntax(item: .stmt(stmt)) - } - return item?.with(\.trailingTrivia, .newline) - }), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - // swiftlint:disable:next closure_body_length - let elseBlock: IfExprSyntax.ElseBody? = { - guard let elseBlocks = elseBody else { - return nil - } - - // Build a chained else-if structure if the builder provided If blocks. - var current: SyntaxProtocol? - - for block in elseBlocks.reversed() { - switch block { - case let thenBlock as Then: - // Leaf `else` – produce a code-block. - let stmts = CodeBlockItemListSyntax( - thenBlock.body.compactMap { element in - if let enumCase = element as? EnumCase { - // Handle EnumCase specially - use expression syntax for enum cases in expressions - return CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)).with( - \.trailingTrivia, .newline) - } else if let decl = element.syntax.as(DeclSyntax.self) { - return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) - } else if let expr = element.syntax.as(ExprSyntax.self) { - return CodeBlockItemSyntax(item: .expr(expr)).with(\.trailingTrivia, .newline) - } else if let stmt = element.syntax.as(StmtSyntax.self) { - return CodeBlockItemSyntax(item: .stmt(stmt)).with(\.trailingTrivia, .newline) - } - return nil - }) - let codeBlock = CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - statements: stmts, - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - current = codeBlock as SyntaxProtocol - - case let ifBlock as If: - guard var ifExpr = ifBlock.syntax.as(IfExprSyntax.self) else { continue } - if let nested = current { - let elseChoice: IfExprSyntax.ElseBody - if let cb = nested.as(CodeBlockSyntax.self) { - elseChoice = IfExprSyntax.ElseBody(cb) - } else if let nestedIf = nested.as(IfExprSyntax.self) { - elseChoice = IfExprSyntax.ElseBody(nestedIf) - } else { - continue - } - - ifExpr = - ifExpr - .with(\.elseKeyword, .keyword(.else, leadingTrivia: .space, trailingTrivia: .space)) - .with(\.elseBody, elseChoice) - } - current = ifExpr as SyntaxProtocol - - default: - // Treat any other CodeBlock as part of a final code-block - let item: CodeBlockItemSyntax? - if let enumCase = block as? EnumCase { - // Handle EnumCase specially - use expression syntax for enum cases in expressions - item = CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)) - } else if let decl = block.syntax.as(DeclSyntax.self) { - item = CodeBlockItemSyntax(item: .decl(decl)) - } else if let expr = block.syntax.as(ExprSyntax.self) { - item = CodeBlockItemSyntax(item: .expr(expr)) - } else if let stmt = block.syntax.as(StmtSyntax.self) { - item = CodeBlockItemSyntax(item: .stmt(stmt)) - } else { - item = nil - } - if let itm = item { - let codeBlock = CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - statements: CodeBlockItemListSyntax([itm.with(\.trailingTrivia, .newline)]), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - current = codeBlock as SyntaxProtocol - } - } - } - - if let final = current { - if let cb = final.as(CodeBlockSyntax.self) { - return IfExprSyntax.ElseBody(cb) - } else if let ifExpr = final.as(IfExprSyntax.self) { - return IfExprSyntax.ElseBody(ifExpr) - } - } - return nil - }() - return ExprSyntax( - IfExprSyntax( - ifKeyword: .keyword(.if, trailingTrivia: .space), - conditions: condList, - body: bodyBlock, - elseKeyword: elseBlock != nil - ? .keyword(.else, leadingTrivia: .space, trailingTrivia: .space) : nil, - elseBody: elseBlock - ) - ) - } -} diff --git a/Sources/SyntaxKit/Parameter.swift b/Sources/SyntaxKit/Parameters/Parameter.swift similarity index 92% rename from Sources/SyntaxKit/Parameter.swift rename to Sources/SyntaxKit/Parameters/Parameter.swift index a5fa4a7..7055911 100644 --- a/Sources/SyntaxKit/Parameter.swift +++ b/Sources/SyntaxKit/Parameters/Parameter.swift @@ -49,14 +49,6 @@ public struct Parameter: CodeBlock { internal var attributes: [AttributeInfo] = [] - /// Creates a parameter for a function or initializer. - /// - Parameters: - /// - name: The name of the parameter. - /// - type: The type of the parameter. - /// - defaultValue: The default value of the parameter, if any. - /// - isUnnamed: A Boolean value that indicates whether the parameter is unnamed. - // NOTE: The previous initializer that accepted an `isUnnamed` flag has been replaced. - /// Creates an unlabeled parameter for function calls or initializers. /// - Parameter value: The value of the parameter. public init(unlabeled value: String) { diff --git a/Sources/SyntaxKit/ParameterBuilderResult.swift b/Sources/SyntaxKit/Parameters/ParameterBuilderResult.swift similarity index 100% rename from Sources/SyntaxKit/ParameterBuilderResult.swift rename to Sources/SyntaxKit/Parameters/ParameterBuilderResult.swift diff --git a/Sources/SyntaxKit/ParameterExp.swift b/Sources/SyntaxKit/Parameters/ParameterExp.swift similarity index 100% rename from Sources/SyntaxKit/ParameterExp.swift rename to Sources/SyntaxKit/Parameters/ParameterExp.swift diff --git a/Sources/SyntaxKit/ParameterExpBuilderResult.swift b/Sources/SyntaxKit/Parameters/ParameterExpBuilderResult.swift similarity index 100% rename from Sources/SyntaxKit/ParameterExpBuilderResult.swift rename to Sources/SyntaxKit/Parameters/ParameterExpBuilderResult.swift diff --git a/Sources/SyntaxKit/PatternConvertible.swift b/Sources/SyntaxKit/PatternConvertible.swift deleted file mode 100644 index 7e502e4..0000000 --- a/Sources/SyntaxKit/PatternConvertible.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// PatternConvertible.swift -// SyntaxKit -// -// Created by Leo Dion. -// Copyright © 2025 BrightDigit. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -import Foundation -import SwiftSyntax - -/// Types that can be turned into a `PatternSyntax` suitable for a `switch` case pattern. -public protocol PatternConvertible { - /// SwiftSyntax representation of the pattern. - var patternSyntax: PatternSyntax { get } -} - -// MARK: - Literal conformance - -extension Literal: PatternConvertible { - /// SwiftSyntax representation of the literal as a pattern. - public var patternSyntax: PatternSyntax { - guard let expr = self.syntax.as(ExprSyntax.self) else { - fatalError("Literal.syntax did not return ExprSyntax") - } - return PatternSyntax(ExpressionPatternSyntax(expression: expr)) - } -} - -// MARK: - Int conformance - -extension Int: PatternConvertible { - /// SwiftSyntax representation of the integer as a pattern. - public var patternSyntax: PatternSyntax { - let expr = ExprSyntax(IntegerLiteralExprSyntax(literal: .integerLiteral(String(self)))) - return PatternSyntax(ExpressionPatternSyntax(expression: expr)) - } -} - -// MARK: - Ranges - -extension Swift.Range: PatternConvertible where Bound == Int { - /// SwiftSyntax representation of the range as a pattern. - public var patternSyntax: PatternSyntax { - let lhs = ExprSyntax( - IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.lowerBound)))) - let op = ExprSyntax(BinaryOperatorExprSyntax(operator: .binaryOperator("..<"))) - let rhs = ExprSyntax( - IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.upperBound)))) - let seq = SequenceExprSyntax(elements: ExprListSyntax([lhs, op, rhs])) - return PatternSyntax(ExpressionPatternSyntax(expression: ExprSyntax(seq))) - } -} - -extension Swift.ClosedRange: PatternConvertible where Bound == Int { - /// SwiftSyntax representation of the closed range as a pattern. - public var patternSyntax: PatternSyntax { - let lhs = ExprSyntax( - IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.lowerBound)))) - let op = ExprSyntax(BinaryOperatorExprSyntax(operator: .binaryOperator("..."))) - let rhs = ExprSyntax( - IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.upperBound)))) - let seq = SequenceExprSyntax(elements: ExprListSyntax([lhs, op, rhs])) - return PatternSyntax(ExpressionPatternSyntax(expression: ExprSyntax(seq))) - } -} - -// MARK: - String identifiers - -extension String: PatternConvertible { - /// SwiftSyntax representation of the string as an identifier pattern. - public var patternSyntax: PatternSyntax { - PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(self))) - } -} - -// MARK: - Let binding pattern - -/// A `let` binding pattern for switch cases. -public struct LetBindingPattern: PatternConvertible { - private let identifier: String - - internal init(identifier: String) { - self.identifier = identifier - } - - /// SwiftSyntax representation of the let binding pattern. - public var patternSyntax: PatternSyntax { - PatternSyntax( - ValueBindingPatternSyntax( - bindingSpecifier: .keyword(.let, trailingTrivia: .space), - pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(identifier))) - ) - ) - } -} - -/// Namespace for pattern creation utilities. -public enum Pattern { - /// Creates a `let` binding pattern for switch cases. - /// - Parameter identifier: The name of the variable to bind. - /// - Returns: A pattern that binds the value to the given identifier. - public static func `let`(_ identifier: String) -> LetBindingPattern { - LetBindingPattern(identifier: identifier) - } -} diff --git a/Sources/SyntaxKit/Patterns/Int+PatternConvertible.swift b/Sources/SyntaxKit/Patterns/Int+PatternConvertible.swift new file mode 100644 index 0000000..e26df13 --- /dev/null +++ b/Sources/SyntaxKit/Patterns/Int+PatternConvertible.swift @@ -0,0 +1,38 @@ +// +// Int+PatternConvertible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Int: PatternConvertible { + /// SwiftSyntax representation of the integer as a pattern. + public var patternSyntax: PatternSyntax { + let expr = ExprSyntax(IntegerLiteralExprSyntax(literal: .integerLiteral(String(self)))) + return PatternSyntax(ExpressionPatternSyntax(expression: expr)) + } +} diff --git a/Sources/SyntaxKit/Patterns/LetBindingPattern.swift b/Sources/SyntaxKit/Patterns/LetBindingPattern.swift new file mode 100644 index 0000000..d9f3f5a --- /dev/null +++ b/Sources/SyntaxKit/Patterns/LetBindingPattern.swift @@ -0,0 +1,61 @@ +// +// LetBindingPattern.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +// MARK: - Let binding pattern + +/// Namespace for pattern creation utilities. +public enum Pattern { + /// Creates a `let` binding pattern for switch cases. + /// - Parameter identifier: The name of the variable to bind. + /// - Returns: A pattern that binds the value to the given identifier. + public static func `let`(_ identifier: String) -> LetBindingPattern { + LetBindingPattern(identifier: identifier) + } +} + +/// A `let` binding pattern for switch cases. +public struct LetBindingPattern: PatternConvertible { + private let identifier: String + + internal init(identifier: String) { + self.identifier = identifier + } + + /// SwiftSyntax representation of the let binding pattern. + public var patternSyntax: PatternSyntax { + PatternSyntax( + ValueBindingPatternSyntax( + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + pattern: PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(identifier))) + ) + ) + } +} diff --git a/Sources/SyntaxKit/Patterns/Range+PatternConvertible.swift b/Sources/SyntaxKit/Patterns/Range+PatternConvertible.swift new file mode 100644 index 0000000..0f4a076 --- /dev/null +++ b/Sources/SyntaxKit/Patterns/Range+PatternConvertible.swift @@ -0,0 +1,68 @@ +// +// Range+PatternConvertible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Range: PatternConvertible where Bound == Int { + /// SwiftSyntax representation of the range as a pattern. + public var patternSyntax: PatternSyntax { + let lhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.lowerBound))) + ) + let operation = ExprSyntax( + BinaryOperatorExprSyntax(operator: .binaryOperator("..<")) + ) + let rhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.upperBound))) + ) + let seq = SequenceExprSyntax( + elements: ExprListSyntax([lhs, operation, rhs]) + ) + return PatternSyntax(ExpressionPatternSyntax(expression: ExprSyntax(seq))) + } +} + +extension ClosedRange: PatternConvertible where Bound == Int { + /// SwiftSyntax representation of the closed range as a pattern. + public var patternSyntax: PatternSyntax { + let lhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.lowerBound))) + ) + let operation = ExprSyntax( + BinaryOperatorExprSyntax(operator: .binaryOperator("...")) + ) + let rhs = ExprSyntax( + IntegerLiteralExprSyntax(literal: .integerLiteral(String(self.upperBound))) + ) + let seq = SequenceExprSyntax( + elements: ExprListSyntax([lhs, operation, rhs]) + ) + return PatternSyntax(ExpressionPatternSyntax(expression: ExprSyntax(seq))) + } +} diff --git a/Sources/SyntaxKit/Patterns/String+PatternConvertible.swift b/Sources/SyntaxKit/Patterns/String+PatternConvertible.swift new file mode 100644 index 0000000..944a50e --- /dev/null +++ b/Sources/SyntaxKit/Patterns/String+PatternConvertible.swift @@ -0,0 +1,37 @@ +// +// String+PatternConvertible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension String: PatternConvertible { + /// SwiftSyntax representation of the string as an identifier pattern. + public var patternSyntax: PatternSyntax { + PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(self))) + } +} diff --git a/Sources/SyntaxKit/Break.swift b/Sources/SyntaxKit/Utilities/Break.swift similarity index 100% rename from Sources/SyntaxKit/Break.swift rename to Sources/SyntaxKit/Utilities/Break.swift diff --git a/Sources/SyntaxKit/Case.swift b/Sources/SyntaxKit/Utilities/Case.swift similarity index 99% rename from Sources/SyntaxKit/Case.swift rename to Sources/SyntaxKit/Utilities/Case.swift index 14951df..9f5eb7a 100644 --- a/Sources/SyntaxKit/Case.swift +++ b/Sources/SyntaxKit/Utilities/Case.swift @@ -79,7 +79,8 @@ public struct Case: CodeBlock { item = item.with(\.trailingComma, .commaToken(trailingTrivia: .space)) } return item - }) + } + ) let statements = CodeBlockItemListSyntax( body.compactMap { @@ -92,7 +93,8 @@ public struct Case: CodeBlock { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - }) + } + ) let label = SwitchCaseLabelSyntax( caseKeyword: .keyword(.case, trailingTrivia: .space), caseItems: caseItems, diff --git a/Sources/SyntaxKit/CommentBuilderResult.swift b/Sources/SyntaxKit/Utilities/CommentBuilderResult.swift similarity index 100% rename from Sources/SyntaxKit/CommentBuilderResult.swift rename to Sources/SyntaxKit/Utilities/CommentBuilderResult.swift diff --git a/Sources/SyntaxKit/Continue.swift b/Sources/SyntaxKit/Utilities/Continue.swift similarity index 100% rename from Sources/SyntaxKit/Continue.swift rename to Sources/SyntaxKit/Utilities/Continue.swift diff --git a/Sources/SyntaxKit/Default.swift b/Sources/SyntaxKit/Utilities/Default.swift similarity index 100% rename from Sources/SyntaxKit/Default.swift rename to Sources/SyntaxKit/Utilities/Default.swift diff --git a/Sources/SyntaxKit/EnumCase+Syntax.swift b/Sources/SyntaxKit/Utilities/EnumCase+Syntax.swift similarity index 100% rename from Sources/SyntaxKit/EnumCase+Syntax.swift rename to Sources/SyntaxKit/Utilities/EnumCase+Syntax.swift diff --git a/Sources/SyntaxKit/EnumCase.swift b/Sources/SyntaxKit/Utilities/EnumCase.swift similarity index 98% rename from Sources/SyntaxKit/EnumCase.swift rename to Sources/SyntaxKit/Utilities/EnumCase.swift index 9a17724..5588426 100644 --- a/Sources/SyntaxKit/EnumCase.swift +++ b/Sources/SyntaxKit/Utilities/EnumCase.swift @@ -111,7 +111,8 @@ public struct EnumCase: CodeBlock { label: nil, colon: nil, expression: ExprSyntax( - DeclReferenceExprSyntax(baseName: .identifier(associated.name))), + DeclReferenceExprSyntax(baseName: .identifier(associated.name)) + ), trailingComma: nil ) } @@ -124,7 +125,8 @@ public struct EnumCase: CodeBlock { leftParen: tuple.leftParen, arguments: tuple.elements, rightParen: tuple.rightParen - )) + ) + ) } else { return ExprSyntax(memberAccess) } diff --git a/Sources/SyntaxKit/Fallthrough.swift b/Sources/SyntaxKit/Utilities/Fallthrough.swift similarity index 100% rename from Sources/SyntaxKit/Fallthrough.swift rename to Sources/SyntaxKit/Utilities/Fallthrough.swift diff --git a/Sources/SyntaxKit/Group.swift b/Sources/SyntaxKit/Utilities/Group.swift similarity index 100% rename from Sources/SyntaxKit/Group.swift rename to Sources/SyntaxKit/Utilities/Group.swift diff --git a/Sources/SyntaxKit/Let.swift b/Sources/SyntaxKit/Utilities/Let.swift similarity index 100% rename from Sources/SyntaxKit/Let.swift rename to Sources/SyntaxKit/Utilities/Let.swift diff --git a/Sources/SyntaxKit/Parenthesized.swift b/Sources/SyntaxKit/Utilities/Parenthesized.swift similarity index 100% rename from Sources/SyntaxKit/Parenthesized.swift rename to Sources/SyntaxKit/Utilities/Parenthesized.swift diff --git a/Sources/SyntaxKit/PropertyRequirement.swift b/Sources/SyntaxKit/Utilities/PropertyRequirement.swift similarity index 100% rename from Sources/SyntaxKit/PropertyRequirement.swift rename to Sources/SyntaxKit/Utilities/PropertyRequirement.swift diff --git a/Sources/SyntaxKit/Then.swift b/Sources/SyntaxKit/Utilities/Then.swift similarity index 100% rename from Sources/SyntaxKit/Then.swift rename to Sources/SyntaxKit/Utilities/Then.swift diff --git a/Sources/SyntaxKit/VariableExp.swift b/Sources/SyntaxKit/VariableExp.swift deleted file mode 100644 index 6870691..0000000 --- a/Sources/SyntaxKit/VariableExp.swift +++ /dev/null @@ -1,214 +0,0 @@ -// -// VariableExp.swift -// SyntaxKit -// -// Created by Leo Dion. -// Copyright © 2025 BrightDigit. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -import SwiftSyntax - -/// An expression that refers to a variable. -public struct VariableExp: CodeBlock, PatternConvertible { - internal let name: String - - /// Creates a variable expression. - /// - Parameter name: The name of the variable. - public init(_ name: String) { - self.name = name - } - - /// Accesses a property on the variable. - /// - Parameter propertyName: The name of the property to access. - /// - Returns: A ``PropertyAccessExp`` that represents the property access. - public func property(_ propertyName: String) -> PropertyAccessExp { - PropertyAccessExp(base: self, propertyName: propertyName) - } - - /// Calls a method on the variable. - /// - Parameter methodName: The name of the method to call. - /// - Returns: A ``FunctionCallExp`` that represents the method call. - public func call(_ methodName: String) -> CodeBlock { - FunctionCallExp(baseName: name, methodName: methodName) - } - - /// Calls a method on the variable with parameters. - /// - Parameters: - /// - methodName: The name of the method to call. - /// - params: A ``ParameterExpBuilder`` that provides the parameters for the method call. - /// - Returns: A ``FunctionCallExp`` that represents the method call. - public func call(_ methodName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) - -> CodeBlock - { - FunctionCallExp(baseName: name, methodName: methodName, parameters: params()) - } - - public var syntax: SyntaxProtocol { - ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) - } - - public var patternSyntax: PatternSyntax { - PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(name))) - } -} - -/// An expression that accesses a property on a base expression. -public struct PropertyAccessExp: CodeBlock { - internal let base: CodeBlock - internal let propertyName: String - - /// Creates a property access expression. - /// - Parameters: - /// - base: The base expression. - /// - propertyName: The name of the property to access. - public init(base: CodeBlock, propertyName: String) { - self.base = base - self.propertyName = propertyName - } - - /// Convenience initializer for backward compatibility (baseName as String). - public init(baseName: String, propertyName: String) { - self.base = VariableExp(baseName) - self.propertyName = propertyName - } - - /// Accesses a property on the current property access expression (chaining). - /// - Parameter propertyName: The name of the next property to access. - /// - Returns: A new ``PropertyAccessExp`` representing the chained property access. - public func property(_ propertyName: String) -> PropertyAccessExp { - PropertyAccessExp(base: self, propertyName: propertyName) - } - - /// Negates the property access expression. - /// - Returns: A negated property access expression. - public func not() -> CodeBlock { - NegatedPropertyAccessExp(base: self) - } - - public var syntax: SyntaxProtocol { - let baseSyntax = - base.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) - let property = TokenSyntax.identifier(propertyName) - return ExprSyntax( - MemberAccessExprSyntax( - base: baseSyntax, - dot: .periodToken(), - name: property - )) - } -} - -/// An expression that negates a property access. -public struct NegatedPropertyAccessExp: CodeBlock { - internal let base: CodeBlock - - /// Creates a negated property access expression. - /// - Parameter base: The base property access expression. - public init(base: CodeBlock) { - self.base = base - } - - /// Backward compatibility initializer for (baseName, propertyName). - public init(baseName: String, propertyName: String) { - self.base = PropertyAccessExp(baseName: baseName, propertyName: propertyName) - } - - public var syntax: SyntaxProtocol { - let memberAccess = - base.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) - return ExprSyntax( - PrefixOperatorExprSyntax( - operator: .prefixOperator("!", leadingTrivia: [], trailingTrivia: []), - expression: memberAccess - ) - ) - } -} - -/// An expression that calls a function. -public struct FunctionCallExp: CodeBlock { - internal let baseName: String - internal let methodName: String - internal let parameters: [ParameterExp] - - /// Creates a function call expression. - /// - Parameters: - /// - baseName: The name of the base variable. - /// - methodName: The name of the method to call. - public init(baseName: String, methodName: String) { - self.baseName = baseName - self.methodName = methodName - self.parameters = [] - } - - /// Creates a function call expression with parameters. - /// - Parameters: - /// - baseName: The name of the base variable. - /// - methodName: The name of the method to call. - /// - parameters: The parameters for the method call. - public init(baseName: String, methodName: String, parameters: [ParameterExp]) { - self.baseName = baseName - self.methodName = methodName - self.parameters = parameters - } - - public var syntax: SyntaxProtocol { - let base = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(baseName))) - let method = TokenSyntax.identifier(methodName) - let args = LabeledExprListSyntax( - parameters.enumerated().map { index, param in - let expr = param.syntax - if let labeled = expr as? LabeledExprSyntax { - var element = labeled - if index < parameters.count - 1 { - element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) - } - return element - } else if let unlabeled = expr as? ExprSyntax { - return TupleExprElementSyntax( - label: nil, - colon: nil, - expression: unlabeled, - trailingComma: index < parameters.count - 1 ? .commaToken(trailingTrivia: .space) : nil - ) - } else { - fatalError("ParameterExp.syntax must return LabeledExprSyntax or ExprSyntax") - } - }) - return ExprSyntax( - FunctionCallExprSyntax( - calledExpression: ExprSyntax( - MemberAccessExprSyntax( - base: base, - dot: .periodToken(), - name: method - )), - leftParen: .leftParenToken(), - arguments: args, - rightParen: .rightParenToken() - )) - } -} diff --git a/Sources/SyntaxKit/ComputedProperty.swift b/Sources/SyntaxKit/Variables/ComputedProperty.swift similarity index 99% rename from Sources/SyntaxKit/ComputedProperty.swift rename to Sources/SyntaxKit/Variables/ComputedProperty.swift index d78e040..2322642 100644 --- a/Sources/SyntaxKit/ComputedProperty.swift +++ b/Sources/SyntaxKit/Variables/ComputedProperty.swift @@ -61,7 +61,9 @@ public struct ComputedProperty: CodeBlock { item = CodeBlockItemSyntax(item: .stmt(stmt)) } return item?.with(\.trailingTrivia, .newline) - })), + } + ) + ), rightBrace: TokenSyntax.rightBraceToken(leadingTrivia: .newline) ) let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) diff --git a/Sources/SyntaxKit/Variable+LiteralInitializers.swift b/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift similarity index 97% rename from Sources/SyntaxKit/Variable+LiteralInitializers.swift rename to Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift index a23ed4e..1b4fc38 100644 --- a/Sources/SyntaxKit/Variable+LiteralInitializers.swift +++ b/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift @@ -32,6 +32,7 @@ import Foundation // MARK: - Variable Literal Initializers extension Variable { + // swiftlint:disable cyclomatic_complexity /// Creates a `let` or `var` declaration with a literal value. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. @@ -63,7 +64,8 @@ extension Variable { // For any other LiteralValue type that doesn't conform to CodeBlock, // create a fallback or throw an error fatalError( - "Variable: Unsupported LiteralValue type that doesn't conform to CodeBlock: \(T.self)") + "Variable: Unsupported LiteralValue type that doesn't conform to CodeBlock: \(T.self)" + ) } self.init( @@ -75,6 +77,8 @@ extension Variable { ) } + // swiftlint:enable cyclomatic_complexity + /// Creates a `let` or `var` declaration with a string literal value. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. diff --git a/Sources/SyntaxKit/Variable+TypedInitializers.swift b/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift similarity index 88% rename from Sources/SyntaxKit/Variable+TypedInitializers.swift rename to Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift index f5f805b..b84e5d6 100644 --- a/Sources/SyntaxKit/Variable+TypedInitializers.swift +++ b/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift @@ -31,6 +31,7 @@ import Foundation // MARK: - Variable Typed Initializers +// swiftlint:disable discouraged_optional_boolean extension Variable { /// Creates a `let` or `var` declaration with an Init value, inferring the type from the Init. /// - Parameters: @@ -39,7 +40,9 @@ extension Variable { /// - equals: An Init expression. /// - explicitType: Whether the variable has an explicit type. public init( - _ kind: VariableKind, name: String, equals defaultValue: Init, + _ kind: VariableKind, + name: String, + equals defaultValue: Init, explicitType: Bool? = nil ) { self.init( @@ -59,7 +62,10 @@ extension Variable { /// - equals: The initial value expression of the variable, if any. /// - explicitType: Whether the variable has an explicit type. public init( - _ kind: VariableKind, name: String, type: String, equals defaultValue: CodeBlock? = nil, + _ kind: VariableKind, + name: String, + type: String, + equals defaultValue: CodeBlock? = nil, explicitType: Bool? = nil ) { let finalExplicitType = explicitType ?? (defaultValue == nil) @@ -80,7 +86,10 @@ extension Variable { /// - equals: A string literal value. /// - explicitType: Whether the variable has an explicit type. public init( - _ kind: VariableKind, name: String, type: String, equals value: String, + _ kind: VariableKind, + name: String, + type: String, + equals value: String, explicitType: Bool? = nil ) { self.init( @@ -100,7 +109,10 @@ extension Variable { /// - equals: An integer literal value. /// - explicitType: Whether the variable has an explicit type. public init( - _ kind: VariableKind, name: String, type: String, equals value: Int, + _ kind: VariableKind, + name: String, + type: String, + equals value: Int, explicitType: Bool? = nil ) { self.init( @@ -120,7 +132,10 @@ extension Variable { /// - equals: A boolean literal value. /// - explicitType: Whether the variable has an explicit type. public init( - _ kind: VariableKind, name: String, type: String, equals value: Bool, + _ kind: VariableKind, + name: String, + type: String, + equals value: Bool, explicitType: Bool? = nil ) { self.init( @@ -140,7 +155,10 @@ extension Variable { /// - equals: A double literal value. /// - explicitType: Whether the variable has an explicit type. public init( - _ kind: VariableKind, name: String, type: String, equals value: Double, + _ kind: VariableKind, + name: String, + type: String, + equals value: Double, explicitType: Bool? = nil ) { self.init( @@ -152,3 +170,4 @@ extension Variable { ) } } +// swiftlint:enable discouraged_optional_boolean diff --git a/Sources/SyntaxKit/Variable.swift b/Sources/SyntaxKit/Variables/Variable.swift similarity index 100% rename from Sources/SyntaxKit/Variable.swift rename to Sources/SyntaxKit/Variables/Variable.swift diff --git a/Sources/SyntaxKit/VariableDecl.swift b/Sources/SyntaxKit/Variables/VariableDecl.swift similarity index 100% rename from Sources/SyntaxKit/VariableDecl.swift rename to Sources/SyntaxKit/Variables/VariableDecl.swift diff --git a/Sources/SyntaxKit/Variables/VariableExp.swift b/Sources/SyntaxKit/Variables/VariableExp.swift new file mode 100644 index 0000000..8e559aa --- /dev/null +++ b/Sources/SyntaxKit/Variables/VariableExp.swift @@ -0,0 +1,74 @@ +// +// VariableExp.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// An expression that refers to a variable. +public struct VariableExp: CodeBlock, PatternConvertible { + internal let name: String + + /// Creates a variable expression. + /// - Parameter name: The name of the variable. + public init(_ name: String) { + self.name = name + } + + /// Accesses a property on the variable. + /// - Parameter propertyName: The name of the property to access. + /// - Returns: A ``PropertyAccessExp`` that represents the property access. + public func property(_ propertyName: String) -> PropertyAccessExp { + PropertyAccessExp(base: self, propertyName: propertyName) + } + + /// Calls a method on the variable. + /// - Parameter methodName: The name of the method to call. + /// - Returns: A ``FunctionCallExp`` that represents the method call. + public func call(_ methodName: String) -> CodeBlock { + FunctionCallExp(baseName: name, methodName: methodName) + } + + /// Calls a method on the variable with parameters. + /// - Parameters: + /// - methodName: The name of the method to call. + /// - params: A ``ParameterExpBuilder`` that provides the parameters for the method call. + /// - Returns: A ``FunctionCallExp`` that represents the method call. + public func call(_ methodName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) + -> CodeBlock + { + FunctionCallExp(baseName: name, methodName: methodName, parameters: params()) + } + + public var syntax: SyntaxProtocol { + ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) + } + + public var patternSyntax: PatternSyntax { + PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(name))) + } +} diff --git a/Sources/SyntaxKit/VariableKind.swift b/Sources/SyntaxKit/Variables/VariableKind.swift similarity index 100% rename from Sources/SyntaxKit/VariableKind.swift rename to Sources/SyntaxKit/Variables/VariableKind.swift diff --git a/Sources/SyntaxKit/parser/String.swift b/Sources/SyntaxKit/parser/String.swift index ee2b142..709fd92 100644 --- a/Sources/SyntaxKit/parser/String.swift +++ b/Sources/SyntaxKit/parser/String.swift @@ -39,7 +39,11 @@ extension String { ] for (unescaped, escaped) in specialCharacters { string = string.replacingOccurrences( - of: unescaped, with: escaped, options: .literal, range: nil) + of: unescaped, + with: escaped, + options: .literal, + range: nil + ) } return string } diff --git a/Sources/SyntaxKit/parser/TokenVisitor.swift b/Sources/SyntaxKit/parser/TokenVisitor.swift index 09a8e3d..4487dcb 100644 --- a/Sources/SyntaxKit/parser/TokenVisitor.swift +++ b/Sources/SyntaxKit/parser/TokenVisitor.swift @@ -63,15 +63,16 @@ internal final class TokenVisitor: SyntaxRewriter { let graphemeStartColumn: Int if let prefix = String( - locationConverter.sourceLines[start.line - 1].utf8.prefix(start.column - 1)) - { + locationConverter.sourceLines[start.line - 1].utf8.prefix(start.column - 1) + ) { graphemeStartColumn = prefix.utf16.count + 1 } else { graphemeStartColumn = start.column } let graphemeEndColumn: Int - if let prefix = String(locationConverter.sourceLines[end.line - 1].utf8.prefix(end.column - 1)) - { + if let prefix = String( + locationConverter.sourceLines[end.line - 1].utf8.prefix(end.column - 1) + ) { graphemeEndColumn = prefix.utf16.count + 1 } else { graphemeEndColumn = end.column @@ -117,7 +118,8 @@ internal final class TokenVisitor: SyntaxRewriter { } guard allChildren.contains(where: { child in child.keyPathInParent == keyPath }) else { treeNode.structure.append( - StructureProperty(name: name, value: StructureValue(text: "nil"))) + StructureProperty(name: name, value: StructureValue(text: "nil")) + ) continue } @@ -166,7 +168,10 @@ internal final class TokenVisitor: SyntaxRewriter { StructureProperty(name: "Element", value: StructureValue(text: "\(syntax)"))) treeNode.structure.append( StructureProperty( - name: "Count", value: StructureValue(text: "\(node.children(viewMode: .all).count)"))) + name: "Count", + value: StructureValue(text: "\(node.children(viewMode: .all).count)") + ) + ) case .choices: break } diff --git a/Sources/SyntaxKit/parser/TreeNode.swift b/Sources/SyntaxKit/parser/TreeNode.swift index a649c78..29ec74c 100644 --- a/Sources/SyntaxKit/parser/TreeNode.swift +++ b/Sources/SyntaxKit/parser/TreeNode.swift @@ -35,7 +35,11 @@ internal final class TreeNode: Codable { internal var text: String internal var range = SourceRange( - startRow: 0, startColumn: 0, endRow: 0, endColumn: 0) + startRow: 0, + startColumn: 0, + endRow: 0, + endColumn: 0 + ) internal var structure = [StructureProperty]() internal var type: SyntaxType internal var token: Token? diff --git a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift index 9aac57b..d8352c1 100644 --- a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift @@ -27,7 +27,8 @@ import Testing // VendingMachine class Class("VendingMachine") { Variable( - .var, name: "inventory", + .var, + name: "inventory", equals: DictionaryExpr([ ( Literal.string("Candy Bar"), @@ -120,9 +121,11 @@ import Testing } class VendingMachine { - var inventory = ["Candy Bar": Item(price: 12, count: 7), - "Chips": Item(price: 10, count: 4), - "Pretzels": Item(price: 7, count: 11)] + var inventory = [ + "Candy Bar": Item(price: 12, count: 7), + "Chips": Item(price: 10, count: 4), + "Pretzels": Item(price: 7, count: 11) + ] var coinsDeposited = 0 func vend(itemNamed name: String) throws { diff --git a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift index 821c215..f5170c6 100644 --- a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift @@ -93,11 +93,11 @@ import Testing Call("print") { ParameterExp( name: "", - value: - "\"The string \"\\(possibleNumber)\" could not be converted to an integer\"" + value: "\"The string \"\\(possibleNumber)\" could not be converted to an integer\"" ) } - }) + } + ) // Multiple optional bindings Variable(.let, name: "possibleName", type: "String?", equals: Literal.string("John")) @@ -118,28 +118,34 @@ import Testing } // MARK: - Guard Statements - Function("greet", { Parameter(name: "person", type: "[String: String]") }) { - Guard { - Let("name", "person[\"name\"]") - } else: { - Call("print") { - ParameterExp(name: "", value: "\"No name provided\"") + Function( + "greet", + { + Parameter(name: "person", type: "[String: String]") + }, + { + Guard { + Let("name", "person[\"name\"]") + } else: { + Call("print") { + ParameterExp(name: "", value: "\"No name provided\"") + } } - } - Guard { - Let("age", "person[\"age\"]") - Let("ageInt", "Int(age)") - } else: { - Call("print") { - ParameterExp(name: "", value: "\"Invalid age provided\"") + Guard { + Let("age", "person[\"age\"]") + Let("ageInt", "Int(age)") + } else: { + Call("print") { + ParameterExp(name: "", value: "\"Invalid age provided\"") + } } - } - Call("print") { - ParameterExp(name: "", value: "\"Hello \\(name), you are \\(ageInt) years old\"") + Call("print") { + ParameterExp(name: "", value: "\"Hello \\(name), you are \\(ageInt) years old\"") + } } - } + ) .comment { Line("MARK: - Guard Statements") } diff --git a/Tests/SyntaxKitTests/Unit/AttributeTests.swift b/Tests/SyntaxKitTests/Unit/Attributes/AttributeTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/AttributeTests.swift rename to Tests/SyntaxKitTests/Unit/Attributes/AttributeTests.swift diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift b/Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentAsyncTests.swift similarity index 94% rename from Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift rename to Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentAsyncTests.swift index 9578aba..4227fd1 100644 --- a/Tests/SyntaxKitTests/Unit/TupleAssignmentAsyncTests.swift +++ b/Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentAsyncTests.swift @@ -34,7 +34,7 @@ import Testing ).async() let generated = tupleAssignment.generateCode() - let expected = "let (result, count) = await (processData(input: \"test\"), 42)" + let expected = "let (result, count) = await (processData(input: \"test\"), " + "42)" #expect(generated.normalize() == expected.normalize()) } @@ -73,7 +73,7 @@ import Testing let generated = tupleAssignment.generateCode() let expected = - "let (data, posts) = try (await fetchUserData(id: 1), await fetchUserPosts(id: 1))" + "let (data, posts) = try (await fetchUserData(id: 1), " + "await fetchUserPosts(id: 1))" #expect(generated.normalize() == expected.normalize()) } @@ -115,7 +115,8 @@ import Testing let generated = tupleAssignment.generateCode() let expected = - "let (user, profile, settings) = try await (await fetchUser(id: 123), await fetchProfile(userId: 123), await fetchSettings(userId: 123))" + "let (user, profile, settings) = try await (await fetchUser(id: 123), " + + "await fetchProfile(userId: 123), await fetchSettings(userId: 123))" #expect(generated.normalize() == expected.normalize()) } diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentBasicTests.swift b/Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentBasicTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/TupleAssignmentBasicTests.swift rename to Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentBasicTests.swift diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentEdgeCaseTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/TupleAssignmentEdgeCaseTests.swift rename to Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentEdgeCaseTests.swift diff --git a/Tests/SyntaxKitTests/Unit/TupleAssignmentIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentIntegrationTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/TupleAssignmentIntegrationTests.swift rename to Tests/SyntaxKitTests/Unit/Collections/TupleAssignmentIntegrationTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ConditionalsTests.swift b/Tests/SyntaxKitTests/Unit/ControlFlow/ConditionalsTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ConditionalsTests.swift rename to Tests/SyntaxKitTests/Unit/ControlFlow/ConditionalsTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ForLoopTests.swift b/Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift similarity index 88% rename from Tests/SyntaxKitTests/Unit/ForLoopTests.swift rename to Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift index f5fd0b2..3b922cf 100644 --- a/Tests/SyntaxKitTests/Unit/ForLoopTests.swift +++ b/Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift @@ -3,9 +3,9 @@ import Testing @testable import SyntaxKit @Suite -final class ForLoopTests { +internal final class ForLoopTests { @Test - func testSimpleForInLoop() { + internal func testSimpleForInLoop() { let forLoop = For( VariableExp("item"), in: VariableExp("items"), @@ -22,7 +22,7 @@ final class ForLoopTests { } @Test - func testForInWithWhereClause() { + internal func testForInWithWhereClause() { let forLoop = For( VariableExp("number"), in: VariableExp("numbers"), diff --git a/Tests/SyntaxKitTests/Unit/PatternConvertibleTests.swift b/Tests/SyntaxKitTests/Unit/Core/PatternConvertibleTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/PatternConvertibleTests.swift rename to Tests/SyntaxKitTests/Unit/Core/PatternConvertibleTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ClassTests.swift b/Tests/SyntaxKitTests/Unit/Declarations/ClassTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ClassTests.swift rename to Tests/SyntaxKitTests/Unit/Declarations/ClassTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ExtensionTests.swift b/Tests/SyntaxKitTests/Unit/Declarations/ExtensionTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ExtensionTests.swift rename to Tests/SyntaxKitTests/Unit/Declarations/ExtensionTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ProtocolTests.swift b/Tests/SyntaxKitTests/Unit/Declarations/ProtocolTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ProtocolTests.swift rename to Tests/SyntaxKitTests/Unit/Declarations/ProtocolTests.swift diff --git a/Tests/SyntaxKitTests/Unit/StructTests.swift b/Tests/SyntaxKitTests/Unit/Declarations/StructTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/StructTests.swift rename to Tests/SyntaxKitTests/Unit/Declarations/StructTests.swift diff --git a/Tests/SyntaxKitTests/Unit/TypeAliasTests.swift b/Tests/SyntaxKitTests/Unit/Declarations/TypeAliasTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/TypeAliasTests.swift rename to Tests/SyntaxKitTests/Unit/Declarations/TypeAliasTests.swift diff --git a/Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/EdgeCaseTests.swift rename to Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTests.swift diff --git a/Tests/SyntaxKitTests/Unit/EdgeCaseTestsExpressions.swift b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsExpressions.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/EdgeCaseTestsExpressions.swift rename to Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsExpressions.swift diff --git a/Tests/SyntaxKitTests/Unit/EdgeCaseTestsTypes.swift b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsTypes.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/EdgeCaseTestsTypes.swift rename to Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsTypes.swift diff --git a/Tests/SyntaxKitTests/Unit/CatchBasicTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/CatchBasicTests.swift similarity index 97% rename from Tests/SyntaxKitTests/Unit/CatchBasicTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/CatchBasicTests.swift index dcaad97..3cb1b6f 100644 --- a/Tests/SyntaxKitTests/Unit/CatchBasicTests.swift +++ b/Tests/SyntaxKitTests/Unit/ErrorHandling/CatchBasicTests.swift @@ -126,7 +126,8 @@ import Testing let generated = doCatch.generateCode() let expected = - "do { try someFunction(param: \"test\") } catch { logError(error: error) print(\"Error: \\(error)\") }" + "do { try someFunction(param: \"test\") } catch { " + "logError(error: error) " + + "print(\"Error: \\(error)\") }" #expect(generated.normalize() == expected.normalize()) } diff --git a/Tests/SyntaxKitTests/Unit/CatchComplexTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/CatchComplexTests.swift similarity index 86% rename from Tests/SyntaxKitTests/Unit/CatchComplexTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/CatchComplexTests.swift index 5fbb362..7356db3 100644 --- a/Tests/SyntaxKitTests/Unit/CatchComplexTests.swift +++ b/Tests/SyntaxKitTests/Unit/ErrorHandling/CatchComplexTests.swift @@ -26,7 +26,8 @@ import Testing let generated = doCatch.generateCode() let expected = - "do { try someFunction(param: \"test\") } catch .requestFailed(let statusCode, let message) { " + "do { try someFunction(param: \"test\") } " + + "catch .requestFailed(let statusCode, let message) { " + "logAPIError(statusCode: statusCode, message: message) }" #expect(generated.normalize() == expected.normalize()) @@ -49,7 +50,8 @@ import Testing let generated = doCatch.generateCode() let expected = - "do { try someFunction(param: \"test\") } catch .connectionFailed { retryConnection(maxAttempts: 3) }" + "do { try someFunction(param: \"test\") } " + + "catch .connectionFailed { retryConnection(maxAttempts: 3) }" #expect(generated.normalize() == expected.normalize()) } @@ -76,7 +78,11 @@ import Testing let generated = doCatch.generateCode() let expected = """ - do { try someFunction(param: "test") } catch .invalidEmail { logValidationError(field: "email") let errorMessage = "Invalid email format" showError(message: errorMessage) } + do { try someFunction(param: "test") } catch .invalidEmail { + logValidationError(field: "email") + let errorMessage = "Invalid email format" + showError(message: errorMessage) + } """ #expect(generated.normalize() == expected.normalize()) @@ -102,7 +108,11 @@ import Testing let generated = doCatch.generateCode() let expected = """ - do { try someFunction(param: "test") } catch .connectionFailed { let retryCount = 0 attemptConnection(attempt: retryCount) incrementRetryCount(current: retryCount) } + do { try someFunction(param: "test") } catch .connectionFailed { + let retryCount = 0 + attemptConnection(attempt: retryCount) + incrementRetryCount(current: retryCount) + } """ #expect(generated.normalize() == expected.normalize()) diff --git a/Tests/SyntaxKitTests/Unit/CatchEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/CatchEdgeCaseTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/CatchEdgeCaseTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/CatchEdgeCaseTests.swift diff --git a/Tests/SyntaxKitTests/Unit/CatchIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/CatchIntegrationTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/CatchIntegrationTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/CatchIntegrationTests.swift diff --git a/Tests/SyntaxKitTests/Unit/DoBasicTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/DoBasicTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/DoBasicTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/DoBasicTests.swift diff --git a/Tests/SyntaxKitTests/Unit/DoComplexTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/DoComplexTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/DoComplexTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/DoComplexTests.swift diff --git a/Tests/SyntaxKitTests/Unit/DoEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/DoEdgeCaseTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/DoEdgeCaseTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/DoEdgeCaseTests.swift diff --git a/Tests/SyntaxKitTests/Unit/DoIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/DoIntegrationTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/DoIntegrationTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/DoIntegrationTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift similarity index 90% rename from Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift index e68a119..ecf8694 100644 --- a/Tests/SyntaxKitTests/Unit/ErrorHandlingTests.swift +++ b/Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift @@ -3,6 +3,7 @@ import Testing @testable import SyntaxKit @Suite internal struct ErrorHandlingTests { + // swiftlint:disable function_body_length @Test("Error handling DSL generates expected Swift code") internal func testErrorHandlingExample() throws { let errorHandlingExample = Group { @@ -52,16 +53,16 @@ import Testing var vendingMachine = VendingMachine() vendingMachine.coinsDeposited = 8 do { - try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) - print("Success! Yum.") + try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) + print("Success! Yum.") } catch .invalidSelection { - print("Invalid Selection.") + print("Invalid Selection.") } catch .outOfStock { - print("Out of Stock.") + print("Out of Stock.") } catch .insufficientFunds(let coinsNeeded) { - print("Insufficient funds. Please insert an additional \\(coinsNeeded) coins.") + print("Insufficient funds. Please insert an additional \\(coinsNeeded) coins.") } catch { - print("Unexpected error: \\(error).") + print("Unexpected error: \\(error).") } """ @@ -72,6 +73,7 @@ import Testing print("Generated code:") print(generated) } + // swiftlint:enable function_body_length @Test("Function with throws clause and unlabeled parameter generates correct syntax") internal func testFunctionWithThrowsClauseAndUnlabeledParameter() throws { diff --git a/Tests/SyntaxKitTests/Unit/ThrowBasicTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowBasicTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ThrowBasicTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowBasicTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowComplexTests.swift similarity index 96% rename from Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowComplexTests.swift index eb8700c..db5c14f 100644 --- a/Tests/SyntaxKitTests/Unit/ThrowComplexTests.swift +++ b/Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowComplexTests.swift @@ -101,7 +101,7 @@ import Testing Parameter(name: "id", type: "Int") } _: { Guard { - VariableExp("id") > Literal.integer(0) + Infix(.greaterThan, lhs: VariableExp("id"), rhs: Literal.integer(0)) } else: { Throw(EnumCase("invalidId")) } @@ -111,7 +111,7 @@ import Testing } }.async() Guard { - VariableExp("user") != Literal.nil + Infix(.notEqual, lhs: VariableExp("user"), rhs: Literal.nil) } else: { Throw(EnumCase("userNotFound")) } diff --git a/Tests/SyntaxKitTests/Unit/ThrowEdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowEdgeCaseTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ThrowEdgeCaseTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowEdgeCaseTests.swift diff --git a/Tests/SyntaxKitTests/Unit/ThrowFunctionTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowFunctionTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/ThrowFunctionTests.swift rename to Tests/SyntaxKitTests/Unit/ErrorHandling/ThrowFunctionTests.swift diff --git a/Tests/SyntaxKitTests/Unit/CallTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/CallTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/CallTests.swift rename to Tests/SyntaxKitTests/Unit/Expressions/CallTests.swift diff --git a/Tests/SyntaxKitTests/Unit/LiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/LiteralTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/LiteralTests.swift rename to Tests/SyntaxKitTests/Unit/Expressions/LiteralTests.swift diff --git a/Tests/SyntaxKitTests/Unit/LiteralValueTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/LiteralValueTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/LiteralValueTests.swift rename to Tests/SyntaxKitTests/Unit/Expressions/LiteralValueTests.swift diff --git a/Tests/SyntaxKitTests/Unit/FunctionTests.swift b/Tests/SyntaxKitTests/Unit/Functions/FunctionTests.swift similarity index 86% rename from Tests/SyntaxKitTests/Unit/FunctionTests.swift rename to Tests/SyntaxKitTests/Unit/Functions/FunctionTests.swift index 5ae2c2f..d6e25bb 100644 --- a/Tests/SyntaxKitTests/Unit/FunctionTests.swift +++ b/Tests/SyntaxKitTests/Unit/Functions/FunctionTests.swift @@ -29,17 +29,19 @@ internal struct FunctionTests { @Test internal func testStaticFunction() throws { let function = Function( - "createInstance", returns: "MyType", + "createInstance", + returns: "MyType", { Parameter(name: "value", type: "String") - } - ) { - Return { - Init("MyType") { - ParameterExp(name: "value", value: Literal.ref("value")) + }, + { + Return { + Init("MyType") { + ParameterExp(name: "value", value: Literal.ref("value")) + } } } - }.static() + ).static() let expected = """ static func createInstance(value: String) -> MyType { @@ -60,10 +62,11 @@ internal struct FunctionTests { "updateValue", { Parameter(name: "newValue", type: "String") + }, + { + Assignment("value", Literal.ref("newValue")) } - ) { - Assignment("value", Literal.ref("newValue")) - }.mutating() + ).mutating() let expected = """ mutating func updateValue(newValue: String) { diff --git a/Tests/SyntaxKitTests/Unit/FrameworkCompatibilityTests.swift b/Tests/SyntaxKitTests/Unit/Integration/FrameworkCompatibilityTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/FrameworkCompatibilityTests.swift rename to Tests/SyntaxKitTests/Unit/Integration/FrameworkCompatibilityTests.swift diff --git a/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTests.swift rename to Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTests.swift diff --git a/Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTestsAPI.swift b/Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTestsAPI.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/OptionsMacroIntegrationTestsAPI.swift rename to Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTestsAPI.swift diff --git a/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift b/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift deleted file mode 100644 index 133d548..0000000 --- a/Tests/SyntaxKitTests/Unit/MainApplicationTests.swift +++ /dev/null @@ -1,198 +0,0 @@ -import Foundation -import Testing - -@testable import SyntaxKit - -internal struct MainApplicationTests { - // MARK: - Main Application Error Handling Tests - - @Test("Main application handles valid input") - internal func testMainApplicationValidInput() throws { - // This test simulates the main application behavior - // We can't easily test the main function directly, but we can test its components - - let code = "let x = 42" - let response = try SyntaxParser.parse(code: code, options: ["fold"]) - - // Test JSON serialization (part of main application logic) - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("syntax")) - #expect(jsonString!.contains("let")) - } - - @Test("Main application handles empty input") - internal func testMainApplicationEmptyInput() throws { - let code = "" - let response = try SyntaxParser.parse(code: code, options: []) - - // Test JSON serialization with empty result - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("syntax")) - } - - @Test("Main application handles parsing errors") - internal func testMainApplicationHandlesParsingErrors() throws { - let invalidCode = "struct {" - - // The parser doesn't throw errors for invalid syntax, it returns a result - let response = try SyntaxParser.parse(code: invalidCode, options: []) - - // Test error JSON serialization (part of main application logic) - let jsonData = try JSONSerialization.data(withJSONObject: ["error": "Invalid syntax"]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("error")) - #expect(jsonString!.contains("Invalid syntax")) - } - - @Test("Main application handles JSON serialization errors") - internal func testMainApplicationHandlesJSONSerializationErrors() throws { - // Test with a response that might cause JSON serialization issues - let code = "let x = 42" - let response = try SyntaxParser.parse(code: code, options: []) - - // This should work fine, but we're testing the JSON serialization path - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - } - - // MARK: - File I/O Simulation Tests - - @Test("Main application handles large input") - internal func testMainApplicationHandlesLargeInput() throws { - // Generate a large Swift file to test performance - var largeCode = "" - for index in 1...50 { - largeCode += """ - struct Struct\(index) { - let property\(index): String - func method\(index)() -> String { - return "value\(index)" - } - } - - """ - } - - let response = try SyntaxParser.parse(code: largeCode, options: ["fold"]) - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("Struct1")) - #expect(jsonString!.contains("Struct50")) - } - - @Test("Main application handles unicode input") - internal func testMainApplicationHandlesUnicodeInput() throws { - let unicodeCode = """ - let emoji = "🚀" - let unicode = "café" - let chinese = "你好" - """ - - let response = try SyntaxParser.parse(code: unicodeCode, options: []) - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("emoji")) - #expect(jsonString!.contains("unicode")) - #expect(jsonString!.contains("chinese")) - } - - // MARK: - Error Response Format Tests - - @Test("Main application error response format") - internal func testMainApplicationErrorResponseFormat() throws { - // Test the error response format that the main application would generate - let testError = NSError( - domain: "TestDomain", - code: 1, - userInfo: [NSLocalizedDescriptionKey: "Test error message"] - ) - - let errorResponse = ["error": testError.localizedDescription] - let jsonData = try JSONSerialization.data(withJSONObject: errorResponse) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("error")) - #expect(jsonString!.contains("Test error message")) - } - - @Test("Main application handles encoding errors") - internal func testMainApplicationHandlesEncodingErrors() throws { - let code = "let x = 42" - let response = try SyntaxParser.parse(code: code, options: []) - - // Test UTF-8 encoding (part of main application logic) - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("syntax")) - } - - // MARK: - Integration Tests - - @Test("Main application integration with complex Swift code") - internal func testMainApplicationIntegrationWithComplexSwiftCode() throws { - let code = """ - @objc class MyClass: NSObject { - @Published var property: String = "default" - - func method(@escaping completion: @escaping (String) -> Void) { - completion("result") - } - - enum NestedEnum: Int { - case first = 1 - case second = 2 - } - } - """ - - let response = try SyntaxParser.parse(code: code, options: ["fold"]) - - // Test JSON serialization (part of main application logic) - let jsonData = try JSONSerialization.data(withJSONObject: ["syntax": response.syntaxJSON]) - let jsonString = String(data: jsonData, encoding: .utf8) - - #expect(jsonString != nil) - #expect(jsonString!.contains("syntax")) - #expect(jsonString!.contains("class")) - #expect(jsonString!.contains("MyClass")) - } - - @Test("Main application handles different parser options") - internal func testMainApplicationHandlesDifferentParserOptions() throws { - let code = "let x = 42" - - let response1 = try SyntaxParser.parse(code: code, options: []) - let response2 = try SyntaxParser.parse(code: code, options: ["fold"]) - - // Test JSON serialization for both responses - let jsonData1 = try JSONSerialization.data(withJSONObject: ["syntax": response1.syntaxJSON]) - let jsonString1 = String(data: jsonData1, encoding: .utf8) - - let jsonData2 = try JSONSerialization.data(withJSONObject: ["syntax": response2.syntaxJSON]) - let jsonString2 = String(data: jsonData2, encoding: .utf8) - - #expect(jsonString1 != nil) - #expect(jsonString2 != nil) - #expect(jsonString1!.contains("syntax")) - #expect(jsonString2!.contains("syntax")) - #expect(jsonString1!.contains("let")) - #expect(jsonString2!.contains("let")) - } -} diff --git a/Tests/SyntaxKitTests/Unit/AssertionMigrationTests.swift b/Tests/SyntaxKitTests/Unit/Migration/AssertionMigrationTests.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/AssertionMigrationTests.swift rename to Tests/SyntaxKitTests/Unit/Migration/AssertionMigrationTests.swift diff --git a/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift b/Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift similarity index 95% rename from Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift rename to Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift index 9591a6e..c92a763 100644 --- a/Tests/SyntaxKitTests/Unit/CodeStyleMigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift @@ -48,7 +48,7 @@ internal struct CodeStyleMigrationTests { // MARK: - Multiline String Formatting Tests - @Test func testMultilineStringFormatting() { + @Test internal func testMultilineStringFormatting() { let expected = """ struct TestStruct { let value: String @@ -68,7 +68,7 @@ internal struct CodeStyleMigrationTests { #expect(normalized == expectedNormalized) } - @Test func testMigrationPreservesCodeGeneration() { + @Test internal func testMigrationPreservesCodeGeneration() { // Ensure that the style changes don't break core functionality let group = Group { Return { diff --git a/Tests/SyntaxKitTests/Unit/MigrationTests.swift b/Tests/SyntaxKitTests/Unit/Migration/MigrationTests.swift similarity index 98% rename from Tests/SyntaxKitTests/Unit/MigrationTests.swift rename to Tests/SyntaxKitTests/Unit/Migration/MigrationTests.swift index ed00bc1..3564d8f 100644 --- a/Tests/SyntaxKitTests/Unit/MigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/Migration/MigrationTests.swift @@ -82,7 +82,10 @@ internal struct MigrationTests { // Test that .regularExpression works instead of String.CompareOptions.regularExpression let testString = "public func test() { }" let result = testString.replacingOccurrences( - of: "public\\s+", with: "", options: .regularExpression) + of: "public\\s+", + with: "", + options: .regularExpression + ) let expected = "func test() { }" #expect(result == expected) } diff --git a/Tests/SyntaxKitTests/Unit/String+Normalize.swift b/Tests/SyntaxKitTests/Unit/Utilities/String+Normalize.swift similarity index 100% rename from Tests/SyntaxKitTests/Unit/String+Normalize.swift rename to Tests/SyntaxKitTests/Unit/Utilities/String+Normalize.swift diff --git a/Tests/SyntaxKitTests/Unit/VariableStaticTests.swift b/Tests/SyntaxKitTests/Unit/Variables/VariableStaticTests.swift similarity index 99% rename from Tests/SyntaxKitTests/Unit/VariableStaticTests.swift rename to Tests/SyntaxKitTests/Unit/Variables/VariableStaticTests.swift index 3ee8dc0..f5fa928 100644 --- a/Tests/SyntaxKitTests/Unit/VariableStaticTests.swift +++ b/Tests/SyntaxKitTests/Unit/Variables/VariableStaticTests.swift @@ -156,7 +156,8 @@ internal struct VariableStaticTests { @Test internal func testMultipleStaticCalls() { let variable = Variable(.let, name: "test", type: "String", equals: Literal.ref("value")) .withExplicitType() - .static().static() + .static() + .static() let generated = variable.generateCode().normalize() // Should still only have one "static" keyword From bb76cdd4ce2b6f39d2d79a837fdf4b7a7525da3a Mon Sep 17 00:00:00 2001 From: leogdion Date: Mon, 23 Jun 2025 20:27:46 -0400 Subject: [PATCH 08/10] Adding SwiftUI View example with closures, result builders, and imports (#81) --- .swiftlint.yml | 4 +- Examples/Completed/swiftui/code.swift | 24 ++ Examples/Completed/swiftui/dsl.swift | 65 ++++++ Examples/Completed/swiftui/syntax.json | 1 + Examples/Remaining/swiftui/code.swift | 103 -------- Line.swift | 58 ----- .../CodeBlocks/CommentedCodeBlock.swift | 2 +- Sources/SyntaxKit/ControlFlow/If+Body.swift | 11 +- .../ControlFlow/If+CodeBlockItem.swift | 4 +- .../SyntaxKit/ControlFlow/If+Conditions.swift | 5 +- .../SyntaxKit/ControlFlow/If+ElseBody.swift | 5 +- Sources/SyntaxKit/Core/CodeBlock.swift | 21 ++ .../SyntaxKit/Core/TypeRepresentable.swift | 41 ++++ Sources/SyntaxKit/Declarations/Import.swift | 144 ++++++++++++ Sources/SyntaxKit/Declarations/Init.swift | 65 +++++- Sources/SyntaxKit/Declarations/Struct.swift | 32 +++ .../SyntaxKit/Expressions/Closure+Body.swift | 77 ++++++ .../Expressions/Closure+Capture.swift | 105 +++++++++ .../Expressions/Closure+Signature.swift | 113 +++++++++ Sources/SyntaxKit/Expressions/Closure.swift | 76 ++++++ .../Expressions/ClosureParameter.swift | 57 +++++ .../ClosureParameterBuilderResult.swift | 67 ++++++ .../SyntaxKit/Expressions/ClosureType.swift | 221 ++++++++++++++++++ .../SyntaxKit/Expressions/ConditionalOp.swift | 88 +++++++ .../Expressions/FunctionCallExp.swift | 94 +++++--- .../Expressions/OptionalChainingExp.swift | 58 +++++ .../SyntaxKit/Expressions/ReferenceExp.swift | 74 ++++++ Sources/SyntaxKit/Expressions/Task.swift | 102 ++++++++ .../FunctionParameterSyntax+Init.swift | 4 +- .../Functions/FunctionRequirement.swift | 4 +- Sources/SyntaxKit/Parameters/Parameter.swift | 11 +- .../SyntaxKit/Parameters/ParameterExp.swift | 25 +- .../{parser => Parser}/SourceRange.swift | 2 +- .../String+Extensions.swift | 0 .../SyntaxKit/{parser => Parser}/String.swift | 0 .../StructureProperty.swift | 4 +- .../{parser => Parser}/StructureValue.swift | 4 +- .../{parser => Parser}/SyntaxParser.swift | 0 .../{parser => Parser}/SyntaxResponse.swift | 0 .../{parser => Parser}/SyntaxType.swift | 0 .../SyntaxKit/{parser => Parser}/Token.swift | 4 +- .../TokenVisitor+Helpers.swift | 4 +- .../{parser => Parser}/TokenVisitor.swift | 15 +- .../{parser => Parser}/TreeNode.swift | 6 +- .../SyntaxKit/Utilities/EnumCase+Syntax.swift | 124 ++++------ Sources/SyntaxKit/Utilities/EnumCase.swift | 17 +- .../Variables/ComputedProperty.swift | 50 +++- .../Variables/Variable+Attributes.swift | 108 +++++++++ .../Variables/Variable+Modifiers.swift | 80 +++++++ .../Variable+TypedInitializers.swift | 24 ++ Sources/SyntaxKit/Variables/Variable.swift | 153 +++++------- Sources/SyntaxKit/Variables/VariableExp.swift | 13 ++ .../Integration/BlackjackTests.swift | 14 +- .../Integration/SwiftUIExampleTests.swift | 192 +++++++++++++++ .../Unit/Declarations/StructTests.swift | 12 +- .../ErrorHandling/ErrorHandlingTests.swift | 13 +- .../ClosureCaptureCoverageTests.swift | 104 +++++++++ .../Expressions/ClosureCoverageTests.swift | 221 ++++++++++++++++++ .../ConditionalOpBasicTests.swift | 136 +++++++++++ .../ConditionalOpComplexTests.swift | 114 +++++++++ .../ConditionalOpLiteralTests.swift | 129 ++++++++++ .../NegatedPropertyAccessExpBasicTests.swift | 53 +++++ ...egatedPropertyAccessExpFunctionTests.swift | 78 +++++++ ...NegatedPropertyAccessExpLiteralTests.swift | 78 +++++++ ...egatedPropertyAccessExpPropertyTests.swift | 84 +++++++ .../OptionalChainingBasicTests.swift | 169 ++++++++++++++ .../OptionalChainingLiteralTests.swift | 91 ++++++++ .../OptionalChainingOperatorTests.swift | 169 ++++++++++++++ .../OptionalChainingPropertyTests.swift | 133 +++++++++++ .../PlusAssign/PlusAssignBasicTests.swift | 138 +++++++++++ .../PlusAssign/PlusAssignLiteralTests.swift | 83 +++++++ .../PlusAssign/PlusAssignPropertyTests.swift | 138 +++++++++++ .../PlusAssignSpecialValueTests.swift | 160 +++++++++++++ .../ReferenceExp/ReferenceExpBasicTests.swift | 149 ++++++++++++ .../ReferenceExpComplexTests.swift | 92 ++++++++ .../ReferenceExpFunctionTests.swift | 85 +++++++ .../ReferenceExpLiteralTests.swift | 99 ++++++++ .../ReferenceExpPropertyTests.swift | 108 +++++++++ .../Unit/SwiftUIFeatureTests.swift | 148 ++++++++++++ .../Unit/Utilities/String+Normalize.swift | 149 +++++++++++- .../Variables/VariableCoverageTests.swift | 193 +++++++++++++++ 81 files changed, 5259 insertions(+), 442 deletions(-) create mode 100644 Examples/Completed/swiftui/code.swift create mode 100644 Examples/Completed/swiftui/dsl.swift create mode 100644 Examples/Completed/swiftui/syntax.json delete mode 100644 Examples/Remaining/swiftui/code.swift delete mode 100644 Line.swift create mode 100644 Sources/SyntaxKit/Core/TypeRepresentable.swift create mode 100644 Sources/SyntaxKit/Declarations/Import.swift create mode 100644 Sources/SyntaxKit/Expressions/Closure+Body.swift create mode 100644 Sources/SyntaxKit/Expressions/Closure+Capture.swift create mode 100644 Sources/SyntaxKit/Expressions/Closure+Signature.swift create mode 100644 Sources/SyntaxKit/Expressions/Closure.swift create mode 100644 Sources/SyntaxKit/Expressions/ClosureParameter.swift create mode 100644 Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift create mode 100644 Sources/SyntaxKit/Expressions/ClosureType.swift create mode 100644 Sources/SyntaxKit/Expressions/ConditionalOp.swift create mode 100644 Sources/SyntaxKit/Expressions/OptionalChainingExp.swift create mode 100644 Sources/SyntaxKit/Expressions/ReferenceExp.swift create mode 100644 Sources/SyntaxKit/Expressions/Task.swift rename Sources/SyntaxKit/{parser => Parser}/SourceRange.swift (97%) rename Sources/SyntaxKit/{parser => Parser}/String+Extensions.swift (100%) rename Sources/SyntaxKit/{parser => Parser}/String.swift (100%) rename Sources/SyntaxKit/{parser => Parser}/StructureProperty.swift (93%) rename Sources/SyntaxKit/{parser => Parser}/StructureValue.swift (94%) rename Sources/SyntaxKit/{parser => Parser}/SyntaxParser.swift (100%) rename Sources/SyntaxKit/{parser => Parser}/SyntaxResponse.swift (100%) rename Sources/SyntaxKit/{parser => Parser}/SyntaxType.swift (100%) rename Sources/SyntaxKit/{parser => Parser}/Token.swift (93%) rename Sources/SyntaxKit/{parser => Parser}/TokenVisitor+Helpers.swift (96%) rename Sources/SyntaxKit/{parser => Parser}/TokenVisitor.swift (95%) rename Sources/SyntaxKit/{parser => Parser}/TreeNode.swift (92%) create mode 100644 Sources/SyntaxKit/Variables/Variable+Attributes.swift create mode 100644 Sources/SyntaxKit/Variables/Variable+Modifiers.swift create mode 100644 Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ClosureCoverageTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpComplexTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpLiteralTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpFunctionTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpLiteralTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpPropertyTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingLiteralTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingOperatorTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingPropertyTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignLiteralTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignPropertyTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignSpecialValueTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift create mode 100644 Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index f9212ce..8623ed2 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -40,7 +40,7 @@ opt_in_rules: - legacy_random - literal_expression_end_indentation - lower_acl_than_parent -# - missing_docs + - missing_docs - modifier_order - multiline_arguments - multiline_arguments_brackets @@ -120,7 +120,7 @@ excluded: - Mint - Examples - Macros - - Sources/SyntaxKit/parser + - Sources/SyntaxKit/Parser indentation_width: indentation_width: 2 file_name: diff --git a/Examples/Completed/swiftui/code.swift b/Examples/Completed/swiftui/code.swift new file mode 100644 index 0000000..4291b69 --- /dev/null +++ b/Examples/Completed/swiftui/code.swift @@ -0,0 +1,24 @@ +public import SwiftUI + + +public struct TodoItemRow: View { + private let item: TodoItem + private let onToggle: @MainActor @Sendable (Date) -> Void + + public var body: some View { + HStack { + Button(action: onToggle) { + Image(systemName: item.isCompleted ? "checkmark.circle.fill" : "circle") + .foregroundColor(item.isCompleted ? .green : .gray) + } + + Button(action: { + Task { @MainActor [weak self] in + self?.onToggle(Date()) + } + }) { + Image(systemName: "trash") + } + } + } +} diff --git a/Examples/Completed/swiftui/dsl.swift b/Examples/Completed/swiftui/dsl.swift new file mode 100644 index 0000000..4e2f97c --- /dev/null +++ b/Examples/Completed/swiftui/dsl.swift @@ -0,0 +1,65 @@ +Import("SwiftUI").access("public") + +Struct("TodoItemRow") { + Variable(.let, name: "item", type: "TodoItem").access("private") + + Variable(.let, name: "onToggle", type: + ClosureType(returns: "Void"){ + ClosureParameter("Date") + } + .attribute("@MainActor") + .attribute("@Sendable") + ) + .access("private") + + ComputedProperty("body", type: "some View") { + Init("HStack") { + ParameterExp(unlabeled: Closure{ + ParameterExp(unlabeled: Closure{ + Init("Button") { + ParameterExp(name: "action", value: VariableExp("onToggle")) + ParameterExp(unlabeled: Closure{ + Init("Image") { + ParameterExp(name: "systemName", value: ConditionalOp( + if: VariableExp("item").property(name: "isCompleted"), + then: Literal.string("checkmark.circle.fill"), + else: Literal.string("circle") + )) + }.call("foregroundColor"){ + ParameterExp(unlabeled: ConditionalOp( + if: VariableExp("item").property(name: "isCompleted"), + then: EnumCase("green"), + else: EnumCase("gray") + )) + } + }) + } + Init("Button") { + ParameterExp(name: "action", value: Closure { + Init("Task") { + ParameterExp(unlabeled: Closure( + capture: { + ParameterExp(unlabeled: VariableExp("self").reference("weak")) + }, + body: { + VariableExp("self").optional().call("onToggle") { + ParameterExp(unlabeled: Init("Date")) + } + } + ).attribute("@MainActor")) + } + }) + ParameterExp(unlabeled: Closure { + Init("Image") { + ParameterExp(name: "systemName", value: Literal.string("trash")) + } + }) + } + }) + }) + + } + } +} +.inherits("View") +.access("public") diff --git a/Examples/Completed/swiftui/syntax.json b/Examples/Completed/swiftui/syntax.json new file mode 100644 index 0000000..4f84ebf --- /dev/null +++ b/Examples/Completed/swiftui/syntax.json @@ -0,0 +1 @@ +[{"text":"SourceFile","id":0,"range":{"endColumn":1,"startRow":1,"startColumn":1,"endRow":25},"type":"other","structure":[{"name":"unexpectedBeforeShebang","value":{"text":"nil"}},{"name":"shebang","value":{"text":"nil"}},{"name":"unexpectedBetweenShebangAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndEndOfFileToken","value":{"text":"nil"}},{"name":"endOfFileToken","value":{"text":"","kind":"endOfFile"}},{"name":"unexpectedAfterEndOfFileToken","value":{"text":"nil"}}]},{"text":"CodeBlockItemList","id":1,"range":{"startRow":1,"endColumn":2,"startColumn":1,"endRow":24},"type":"collection","parent":0,"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}]},{"text":"CodeBlockItem","id":2,"range":{"startColumn":1,"endColumn":22,"endRow":1,"startRow":1},"type":"other","parent":1,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"ImportDeclSyntax"},"name":"item","ref":"ImportDeclSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}]},{"text":"ImportDecl","id":3,"range":{"endRow":1,"endColumn":22,"startRow":1,"startColumn":1},"type":"decl","parent":2,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax","name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax","name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndImportKeyword"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.import)","text":"import"},"name":"importKeyword"},{"value":{"text":"nil"},"name":"unexpectedBetweenImportKeywordAndImportKindSpecifier"},{"value":{"text":"nil"},"name":"importKindSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenImportKindSpecifierAndPath"},{"value":{"text":"ImportPathComponentListSyntax"},"ref":"ImportPathComponentListSyntax","name":"path"},{"value":{"text":"nil"},"name":"unexpectedAfterPath"}]},{"text":"AttributeList","id":4,"range":{"startColumn":1,"endColumn":1,"endRow":1,"startRow":1},"type":"collection","parent":3,"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}]},{"text":"DeclModifierList","id":5,"range":{"startColumn":1,"endColumn":7,"endRow":1,"startRow":1},"type":"collection","parent":3,"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"1"}}]},{"text":"DeclModifier","id":6,"range":{"startColumn":1,"endColumn":7,"endRow":1,"startRow":1},"type":"other","parent":5,"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"public","kind":"keyword(SwiftSyntax.Keyword.public)"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndDetail"},{"value":{"text":"nil"},"name":"detail"},{"value":{"text":"nil"},"name":"unexpectedAfterDetail"}]},{"id":7,"token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.public)","trailingTrivia":"␣<\/span>"},"text":"public","parent":6,"range":{"startColumn":1,"endColumn":7,"endRow":1,"startRow":1},"structure":[],"type":"other"},{"id":8,"range":{"startColumn":8,"endColumn":14,"endRow":1,"startRow":1},"type":"other","parent":3,"structure":[],"token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.import)","trailingTrivia":"␣<\/span>"},"text":"import"},{"text":"ImportPathComponentList","id":9,"range":{"startColumn":15,"endColumn":22,"endRow":1,"startRow":1},"type":"collection","parent":3,"structure":[{"value":{"text":"ImportPathComponentSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}]},{"text":"ImportPathComponent","id":10,"range":{"startColumn":15,"startRow":1,"endColumn":22,"endRow":1},"type":"other","parent":9,"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("SwiftUI")","text":"SwiftUI"}},{"name":"unexpectedBetweenNameAndTrailingPeriod","value":{"text":"nil"}},{"name":"trailingPeriod","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingPeriod","value":{"text":"nil"}}]},{"range":{"startRow":1,"endRow":1,"endColumn":22,"startColumn":15},"structure":[],"type":"other","parent":10,"id":11,"text":"SwiftUI","token":{"kind":"identifier("SwiftUI")","leadingTrivia":"","trailingTrivia":""}},{"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"StructDeclSyntax","name":"item","value":{"text":"StructDeclSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"text":"CodeBlockItem","type":"other","parent":1,"range":{"endRow":24,"startColumn":1,"startRow":4,"endColumn":2},"id":12},{"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"ref":"AttributeListSyntax","name":"attributes","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"ref":"DeclModifierListSyntax","name":"modifiers","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndStructKeyword","value":{"text":"nil"}},{"name":"structKeyword","value":{"text":"struct","kind":"keyword(SwiftSyntax.Keyword.struct)"}},{"name":"unexpectedBetweenStructKeywordAndName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("TodoItemRow")","text":"TodoItemRow"}},{"name":"unexpectedBetweenNameAndGenericParameterClause","value":{"text":"nil"}},{"name":"genericParameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericParameterClauseAndInheritanceClause","value":{"text":"nil"}},{"ref":"InheritanceClauseSyntax","name":"inheritanceClause","value":{"text":"InheritanceClauseSyntax"}},{"name":"unexpectedBetweenInheritanceClauseAndGenericWhereClause","value":{"text":"nil"}},{"name":"genericWhereClause","value":{"text":"nil"}},{"name":"unexpectedBetweenGenericWhereClauseAndMemberBlock","value":{"text":"nil"}},{"ref":"MemberBlockSyntax","name":"memberBlock","value":{"text":"MemberBlockSyntax"}},{"name":"unexpectedAfterMemberBlock","value":{"text":"nil"}}],"text":"StructDecl","type":"decl","parent":12,"range":{"endColumn":2,"endRow":24,"startColumn":1,"startRow":4},"id":13},{"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"text":"AttributeList","type":"collection","parent":13,"range":{"endRow":1,"startRow":1,"endColumn":22,"startColumn":22},"id":14},{"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"1"}}],"text":"DeclModifierList","type":"collection","parent":13,"range":{"endColumn":7,"startColumn":1,"endRow":4,"startRow":4},"id":15},{"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"public","kind":"keyword(SwiftSyntax.Keyword.public)"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndDetail"},{"value":{"text":"nil"},"name":"detail"},{"value":{"text":"nil"},"name":"unexpectedAfterDetail"}],"text":"DeclModifier","type":"other","parent":15,"range":{"endColumn":7,"startRow":4,"endRow":4,"startColumn":1},"id":16},{"parent":16,"text":"public","type":"other","id":17,"structure":[],"token":{"leadingTrivia":"↲<\/span>↲<\/span>↲<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.public)"},"range":{"startColumn":1,"endRow":4,"endColumn":7,"startRow":4}},{"id":18,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.struct)"},"parent":13,"type":"other","text":"struct","range":{"startColumn":8,"endRow":4,"endColumn":14,"startRow":4}},{"type":"other","structure":[],"id":19,"range":{"startColumn":15,"endRow":4,"endColumn":26,"startRow":4},"text":"TodoItemRow","parent":13,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("TodoItemRow")"}},{"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndInheritedTypes","value":{"text":"nil"}},{"ref":"InheritedTypeListSyntax","name":"inheritedTypes","value":{"text":"InheritedTypeListSyntax"}},{"name":"unexpectedAfterInheritedTypes","value":{"text":"nil"}}],"text":"InheritanceClause","type":"other","parent":13,"range":{"startColumn":26,"endRow":4,"endColumn":32,"startRow":4},"id":20},{"structure":[],"parent":20,"text":":","type":"other","id":21,"range":{"endRow":4,"startColumn":26,"endColumn":27,"startRow":4},"token":{"kind":"colon","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"startRow":4,"endColumn":32,"endRow":4,"startColumn":28},"structure":[{"name":"Element","value":{"text":"InheritedTypeSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":20,"text":"InheritedTypeList","type":"collection","id":22},{"range":{"startColumn":28,"endColumn":32,"endRow":4,"startRow":4},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeType"},{"value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax","name":"type"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":22,"text":"InheritedType","type":"other","id":23},{"range":{"startRow":4,"endColumn":32,"startColumn":28,"endRow":4},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("View")","text":"View"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"parent":23,"text":"IdentifierType","type":"type","id":24},{"type":"other","range":{"startRow":4,"endColumn":32,"startColumn":28,"endRow":4},"id":25,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("View")"},"text":"View","parent":24,"structure":[]},{"range":{"startRow":4,"endColumn":2,"startColumn":33,"endRow":24},"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndMembers","value":{"text":"nil"}},{"name":"members","value":{"text":"MemberBlockItemListSyntax"},"ref":"MemberBlockItemListSyntax"},{"name":"unexpectedBetweenMembersAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"parent":13,"text":"MemberBlock","type":"other","id":26},{"type":"other","range":{"startColumn":33,"endRow":4,"startRow":4,"endColumn":34},"text":"{","id":27,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftBrace"},"structure":[],"parent":26},{"range":{"startColumn":3,"endRow":23,"startRow":5,"endColumn":4},"structure":[{"value":{"text":"MemberBlockItemSyntax"},"name":"Element"},{"value":{"text":"3"},"name":"Count"}],"parent":26,"text":"MemberBlockItemList","type":"collection","id":28},{"range":{"startColumn":3,"endColumn":29,"endRow":5,"startRow":5},"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":28,"text":"MemberBlockItem","type":"other","id":29},{"range":{"endRow":5,"startRow":5,"startColumn":3,"endColumn":29},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","value":{"text":"DeclModifierListSyntax"},"ref":"DeclModifierListSyntax"},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"kind":"keyword(SwiftSyntax.Keyword.let)","text":"let"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","value":{"text":"PatternBindingListSyntax"},"ref":"PatternBindingListSyntax"},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"parent":29,"text":"VariableDecl","type":"decl","id":30},{"range":{"endRow":4,"endColumn":34,"startRow":4,"startColumn":34},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"parent":30,"text":"AttributeList","type":"collection","id":31},{"range":{"endRow":5,"endColumn":10,"startColumn":3,"startRow":5},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":30,"text":"DeclModifierList","type":"collection","id":32},{"range":{"endRow":5,"startColumn":3,"startRow":5,"endColumn":10},"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"keyword(SwiftSyntax.Keyword.private)","text":"private"}},{"name":"unexpectedBetweenNameAndDetail","value":{"text":"nil"}},{"name":"detail","value":{"text":"nil"}},{"name":"unexpectedAfterDetail","value":{"text":"nil"}}],"parent":32,"text":"DeclModifier","type":"other","id":33},{"type":"other","text":"private","range":{"startRow":5,"startColumn":3,"endRow":5,"endColumn":10},"id":34,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.private)","trailingTrivia":"␣<\/span>"},"structure":[],"parent":33},{"type":"other","id":35,"text":"let","token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"range":{"startRow":5,"startColumn":11,"endRow":5,"endColumn":14},"parent":30,"structure":[]},{"range":{"startRow":5,"startColumn":15,"endRow":5,"endColumn":29},"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":30,"text":"PatternBindingList","type":"collection","id":36},{"range":{"endRow":5,"endColumn":29,"startColumn":15,"startRow":5},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"ref":"TypeAnnotationSyntax","value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"nil"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"value":{"text":"nil"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":36,"text":"PatternBinding","type":"other","id":37},{"range":{"startRow":5,"startColumn":15,"endRow":5,"endColumn":19},"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"item","kind":"identifier("item")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"parent":37,"text":"IdentifierPattern","type":"pattern","id":38},{"token":{"kind":"identifier("item")","leadingTrivia":"","trailingTrivia":""},"text":"item","id":39,"range":{"endColumn":19,"startRow":5,"endRow":5,"startColumn":15},"parent":38,"type":"other","structure":[]},{"range":{"endColumn":29,"startRow":5,"endRow":5,"startColumn":19},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterType"}],"parent":37,"text":"TypeAnnotation","type":"other","id":40},{"id":41,"parent":40,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"text":":","range":{"endRow":5,"startColumn":19,"startRow":5,"endColumn":20},"type":"other","structure":[]},{"range":{"endRow":5,"startColumn":21,"startRow":5,"endColumn":29},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"TodoItem","kind":"identifier("TodoItem")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"parent":40,"text":"IdentifierType","type":"type","id":42},{"parent":42,"range":{"startRow":5,"endRow":5,"startColumn":21,"endColumn":29},"text":"TodoItem","type":"other","id":43,"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("TodoItem")"},"structure":[]},{"range":{"startRow":6,"endRow":6,"startColumn":3,"endColumn":60},"structure":[{"name":"unexpectedBeforeDecl","value":{"text":"nil"}},{"name":"decl","ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"}},{"name":"unexpectedBetweenDeclAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":28,"text":"MemberBlockItem","type":"other","id":44},{"range":{"startRow":6,"endRow":6,"endColumn":60,"startColumn":3},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"}},{"name":"unexpectedBetweenAttributesAndModifiers","value":{"text":"nil"}},{"name":"modifiers","ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"}},{"name":"unexpectedBetweenModifiersAndBindingSpecifier","value":{"text":"nil"}},{"name":"bindingSpecifier","value":{"text":"let","kind":"keyword(SwiftSyntax.Keyword.let)"}},{"name":"unexpectedBetweenBindingSpecifierAndBindings","value":{"text":"nil"}},{"name":"bindings","ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"}},{"name":"unexpectedAfterBindings","value":{"text":"nil"}}],"parent":44,"text":"VariableDecl","type":"decl","id":45},{"range":{"endRow":5,"startRow":5,"endColumn":29,"startColumn":29},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"parent":45,"text":"AttributeList","type":"collection","id":46},{"range":{"startRow":6,"startColumn":3,"endRow":6,"endColumn":10},"structure":[{"name":"Element","value":{"text":"DeclModifierSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":45,"text":"DeclModifierList","type":"collection","id":47},{"range":{"endColumn":10,"endRow":6,"startRow":6,"startColumn":3},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"private","kind":"keyword(SwiftSyntax.Keyword.private)"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndDetail"},{"value":{"text":"nil"},"name":"detail"},{"value":{"text":"nil"},"name":"unexpectedAfterDetail"}],"parent":47,"text":"DeclModifier","type":"other","id":48},{"id":49,"text":"private","parent":48,"type":"other","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.private)","trailingTrivia":"␣<\/span>"},"structure":[],"range":{"startColumn":3,"startRow":6,"endRow":6,"endColumn":10}},{"type":"other","text":"let","token":{"leadingTrivia":"","kind":"keyword(SwiftSyntax.Keyword.let)","trailingTrivia":"␣<\/span>"},"structure":[],"id":50,"range":{"startColumn":11,"startRow":6,"endRow":6,"endColumn":14},"parent":45},{"range":{"startColumn":15,"startRow":6,"endRow":6,"endColumn":60},"structure":[{"value":{"text":"PatternBindingSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":45,"text":"PatternBindingList","type":"collection","id":51},{"range":{"endColumn":60,"startRow":6,"startColumn":15,"endRow":6},"structure":[{"name":"unexpectedBeforePattern","value":{"text":"nil"}},{"name":"pattern","ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"}},{"name":"unexpectedBetweenPatternAndTypeAnnotation","value":{"text":"nil"}},{"name":"typeAnnotation","ref":"TypeAnnotationSyntax","value":{"text":"TypeAnnotationSyntax"}},{"name":"unexpectedBetweenTypeAnnotationAndInitializer","value":{"text":"nil"}},{"name":"initializer","value":{"text":"nil"}},{"name":"unexpectedBetweenInitializerAndAccessorBlock","value":{"text":"nil"}},{"name":"accessorBlock","value":{"text":"nil"}},{"name":"unexpectedBetweenAccessorBlockAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":51,"text":"PatternBinding","type":"other","id":52},{"range":{"endRow":6,"startRow":6,"endColumn":23,"startColumn":15},"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"kind":"identifier("onToggle")","text":"onToggle"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"parent":52,"text":"IdentifierPattern","type":"pattern","id":53},{"text":"onToggle","range":{"endRow":6,"startRow":6,"startColumn":15,"endColumn":23},"structure":[],"type":"other","token":{"leadingTrivia":"","kind":"identifier("onToggle")","trailingTrivia":""},"parent":53,"id":54},{"range":{"endRow":6,"startRow":6,"startColumn":23,"endColumn":60},"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","value":{"text":"AttributedTypeSyntax"},"ref":"AttributedTypeSyntax"},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"parent":52,"text":"TypeAnnotation","type":"other","id":55},{"structure":[],"text":":","token":{"leadingTrivia":"","kind":"colon","trailingTrivia":"␣<\/span>"},"type":"other","parent":55,"range":{"endRow":6,"startRow":6,"startColumn":23,"endColumn":24},"id":56},{"range":{"endRow":6,"startRow":6,"startColumn":25,"endColumn":60},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeSpecifiers"},{"ref":"TypeSpecifierListSyntax","value":{"text":"TypeSpecifierListSyntax"},"name":"specifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenSpecifiersAndAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndBaseType"},{"ref":"FunctionTypeSyntax","value":{"text":"FunctionTypeSyntax"},"name":"baseType"},{"value":{"text":"nil"},"name":"unexpectedAfterBaseType"}],"parent":55,"text":"AttributedType","type":"type","id":57},{"range":{"endRow":6,"startRow":6,"startColumn":25,"endColumn":25},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":57,"text":"TypeSpecifierList","type":"collection","id":58},{"range":{"startColumn":25,"endRow":6,"endColumn":45,"startRow":6},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"2"},"name":"Count"}],"parent":57,"text":"AttributeList","type":"collection","id":59},{"range":{"startColumn":25,"endRow":6,"startRow":6,"endColumn":35},"structure":[{"name":"unexpectedBeforeAtSign","value":{"text":"nil"}},{"name":"atSign","value":{"text":"@","kind":"atSign"}},{"name":"unexpectedBetweenAtSignAndAttributeName","value":{"text":"nil"}},{"name":"attributeName","value":{"text":"IdentifierTypeSyntax"},"ref":"IdentifierTypeSyntax"},{"name":"unexpectedBetweenAttributeNameAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"nil"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"nil"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":"nil"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":59,"text":"Attribute","type":"other","id":60},{"id":61,"token":{"kind":"atSign","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"startColumn":25,"startRow":6,"endRow":6,"endColumn":26},"text":"@","type":"other","parent":60},{"range":{"startColumn":26,"startRow":6,"endRow":6,"endColumn":35},"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"kind":"identifier("MainActor")","text":"MainActor"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"parent":60,"text":"IdentifierType","type":"type","id":62},{"token":{"trailingTrivia":"␣<\/span>","kind":"identifier("MainActor")","leadingTrivia":""},"structure":[],"parent":62,"type":"other","range":{"endRow":6,"endColumn":35,"startRow":6,"startColumn":26},"id":63,"text":"MainActor"},{"range":{"endRow":6,"endColumn":45,"startRow":6,"startColumn":36},"structure":[{"name":"unexpectedBeforeAtSign","value":{"text":"nil"}},{"name":"atSign","value":{"kind":"atSign","text":"@"}},{"name":"unexpectedBetweenAtSignAndAttributeName","value":{"text":"nil"}},{"name":"attributeName","ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenAttributeNameAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"nil"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"nil"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":"nil"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":59,"text":"Attribute","type":"other","id":64},{"type":"other","token":{"leadingTrivia":"","trailingTrivia":"","kind":"atSign"},"text":"@","structure":[],"range":{"startRow":6,"startColumn":36,"endColumn":37,"endRow":6},"id":65,"parent":64},{"range":{"startRow":6,"startColumn":37,"endColumn":45,"endRow":6},"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Sendable","kind":"identifier("Sendable")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"parent":64,"text":"IdentifierType","type":"type","id":66},{"range":{"endColumn":45,"startColumn":37,"startRow":6,"endRow":6},"parent":66,"structure":[],"text":"Sendable","type":"other","id":67,"token":{"kind":"identifier("Sendable")","leadingTrivia":"","trailingTrivia":"␣<\/span>"}},{"range":{"endColumn":60,"startColumn":46,"startRow":6,"endRow":6},"structure":[{"name":"unexpectedBeforeLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndParameters","value":{"text":"nil"}},{"name":"parameters","ref":"TupleTypeElementListSyntax","value":{"text":"TupleTypeElementListSyntax"}},{"name":"unexpectedBetweenParametersAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","ref":"ReturnClauseSyntax","value":{"text":"ReturnClauseSyntax"}},{"name":"unexpectedAfterReturnClause","value":{"text":"nil"}}],"parent":57,"text":"FunctionType","type":"type","id":68},{"text":"(","type":"other","id":69,"range":{"startRow":6,"endRow":6,"startColumn":46,"endColumn":47},"structure":[],"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"parent":68},{"range":{"startRow":6,"endRow":6,"startColumn":47,"endColumn":51},"structure":[{"value":{"text":"TupleTypeElementSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":68,"text":"TupleTypeElementList","type":"collection","id":70},{"range":{"startRow":6,"startColumn":47,"endColumn":51,"endRow":6},"structure":[{"name":"unexpectedBeforeInoutKeyword","value":{"text":"nil"}},{"name":"inoutKeyword","value":{"text":"nil"}},{"name":"unexpectedBetweenInoutKeywordAndFirstName","value":{"text":"nil"}},{"name":"firstName","value":{"text":"nil"}},{"name":"unexpectedBetweenFirstNameAndSecondName","value":{"text":"nil"}},{"name":"secondName","value":{"text":"nil"}},{"name":"unexpectedBetweenSecondNameAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"}},{"name":"unexpectedBetweenTypeAndEllipsis","value":{"text":"nil"}},{"name":"ellipsis","value":{"text":"nil"}},{"name":"unexpectedBetweenEllipsisAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":70,"text":"TupleTypeElement","type":"other","id":71},{"range":{"startRow":6,"startColumn":47,"endColumn":51,"endRow":6},"structure":[{"name":"unexpectedBeforeName","value":{"text":"nil"}},{"name":"name","value":{"text":"Date","kind":"identifier("Date")"}},{"name":"unexpectedBetweenNameAndGenericArgumentClause","value":{"text":"nil"}},{"name":"genericArgumentClause","value":{"text":"nil"}},{"name":"unexpectedAfterGenericArgumentClause","value":{"text":"nil"}}],"parent":71,"text":"IdentifierType","type":"type","id":72},{"parent":72,"structure":[],"token":{"leadingTrivia":"","kind":"identifier("Date")","trailingTrivia":""},"id":73,"range":{"startRow":6,"startColumn":47,"endColumn":51,"endRow":6},"type":"other","text":"Date"},{"id":74,"range":{"startRow":6,"startColumn":51,"endColumn":52,"endRow":6},"parent":68,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":"␣<\/span>"},"structure":[],"type":"other","text":")"},{"range":{"startRow":6,"startColumn":53,"endColumn":60,"endRow":6},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeArrow"},{"value":{"kind":"arrow","text":"->"},"name":"arrow"},{"value":{"text":"nil"},"name":"unexpectedBetweenArrowAndType"},{"value":{"text":"IdentifierTypeSyntax"},"name":"type","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterType"}],"parent":68,"text":"ReturnClause","type":"other","id":75},{"id":76,"range":{"startColumn":53,"endColumn":55,"startRow":6,"endRow":6},"parent":75,"text":"->","type":"other","structure":[],"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"arrow"}},{"range":{"startColumn":56,"endColumn":60,"startRow":6,"endRow":6},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"Void","kind":"identifier("Void")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"parent":75,"text":"IdentifierType","type":"type","id":77},{"token":{"kind":"identifier("Void")","leadingTrivia":"","trailingTrivia":""},"parent":77,"range":{"startColumn":56,"endRow":6,"endColumn":60,"startRow":6},"text":"Void","type":"other","structure":[],"id":78},{"range":{"startColumn":3,"endRow":23,"endColumn":4,"startRow":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeDecl"},{"ref":"VariableDeclSyntax","value":{"text":"VariableDeclSyntax"},"name":"decl"},{"value":{"text":"nil"},"name":"unexpectedBetweenDeclAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":28,"text":"MemberBlockItem","type":"other","id":79},{"range":{"startColumn":3,"startRow":8,"endRow":23,"endColumn":4},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAttributes"},{"ref":"AttributeListSyntax","value":{"text":"AttributeListSyntax"},"name":"attributes"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributesAndModifiers"},{"ref":"DeclModifierListSyntax","value":{"text":"DeclModifierListSyntax"},"name":"modifiers"},{"value":{"text":"nil"},"name":"unexpectedBetweenModifiersAndBindingSpecifier"},{"value":{"text":"var","kind":"keyword(SwiftSyntax.Keyword.var)"},"name":"bindingSpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenBindingSpecifierAndBindings"},{"ref":"PatternBindingListSyntax","value":{"text":"PatternBindingListSyntax"},"name":"bindings"},{"value":{"text":"nil"},"name":"unexpectedAfterBindings"}],"parent":79,"text":"VariableDecl","type":"decl","id":80},{"range":{"startRow":6,"endRow":6,"startColumn":60,"endColumn":60},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"0"}}],"parent":80,"text":"AttributeList","type":"collection","id":81},{"range":{"endRow":8,"startColumn":3,"startRow":8,"endColumn":9},"structure":[{"value":{"text":"DeclModifierSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":80,"text":"DeclModifierList","type":"collection","id":82},{"range":{"startColumn":3,"endRow":8,"endColumn":9,"startRow":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"keyword(SwiftSyntax.Keyword.public)","text":"public"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndDetail"},{"value":{"text":"nil"},"name":"detail"},{"value":{"text":"nil"},"name":"unexpectedAfterDetail"}],"parent":82,"text":"DeclModifier","type":"other","id":83},{"type":"other","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>↲<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.public)"},"text":"public","parent":83,"id":84,"range":{"startColumn":3,"endRow":8,"endColumn":9,"startRow":8},"structure":[]},{"id":85,"structure":[],"range":{"startColumn":10,"endRow":8,"endColumn":13,"startRow":8},"parent":80,"text":"var","token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"keyword(SwiftSyntax.Keyword.var)"},"type":"other"},{"range":{"startColumn":14,"endRow":23,"endColumn":4,"startRow":8},"structure":[{"name":"Element","value":{"text":"PatternBindingSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":80,"text":"PatternBindingList","type":"collection","id":86},{"range":{"endColumn":4,"startRow":8,"startColumn":14,"endRow":23},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforePattern"},{"ref":"IdentifierPatternSyntax","value":{"text":"IdentifierPatternSyntax"},"name":"pattern"},{"value":{"text":"nil"},"name":"unexpectedBetweenPatternAndTypeAnnotation"},{"ref":"TypeAnnotationSyntax","value":{"text":"TypeAnnotationSyntax"},"name":"typeAnnotation"},{"value":{"text":"nil"},"name":"unexpectedBetweenTypeAnnotationAndInitializer"},{"value":{"text":"nil"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndAccessorBlock"},{"ref":"AccessorBlockSyntax","value":{"text":"AccessorBlockSyntax"},"name":"accessorBlock"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorBlockAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":86,"text":"PatternBinding","type":"other","id":87},{"range":{"endRow":8,"endColumn":18,"startRow":8,"startColumn":14},"structure":[{"name":"unexpectedBeforeIdentifier","value":{"text":"nil"}},{"name":"identifier","value":{"text":"body","kind":"identifier("body")"}},{"name":"unexpectedAfterIdentifier","value":{"text":"nil"}}],"parent":87,"text":"IdentifierPattern","type":"pattern","id":88},{"parent":88,"id":89,"range":{"startColumn":14,"endColumn":18,"startRow":8,"endRow":8},"text":"body","type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("body")"},"structure":[]},{"range":{"startColumn":18,"endColumn":29,"startRow":8,"endRow":8},"structure":[{"name":"unexpectedBeforeColon","value":{"text":"nil"}},{"name":"colon","value":{"text":":","kind":"colon"}},{"name":"unexpectedBetweenColonAndType","value":{"text":"nil"}},{"name":"type","ref":"SomeOrAnyTypeSyntax","value":{"text":"SomeOrAnyTypeSyntax"}},{"name":"unexpectedAfterType","value":{"text":"nil"}}],"parent":87,"text":"TypeAnnotation","type":"other","id":90},{"text":":","token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"parent":90,"id":91,"range":{"endRow":8,"endColumn":19,"startRow":8,"startColumn":18},"structure":[],"type":"other"},{"range":{"endRow":8,"endColumn":29,"startRow":8,"startColumn":20},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeSomeOrAnySpecifier"},{"value":{"text":"some","kind":"keyword(SwiftSyntax.Keyword.some)"},"name":"someOrAnySpecifier"},{"value":{"text":"nil"},"name":"unexpectedBetweenSomeOrAnySpecifierAndConstraint"},{"value":{"text":"IdentifierTypeSyntax"},"name":"constraint","ref":"IdentifierTypeSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterConstraint"}],"parent":90,"text":"SomeOrAnyType","type":"type","id":92},{"parent":92,"id":93,"structure":[],"type":"other","text":"some","token":{"kind":"keyword(SwiftSyntax.Keyword.some)","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"endRow":8,"startRow":8,"startColumn":20,"endColumn":24}},{"range":{"endRow":8,"startRow":8,"startColumn":25,"endColumn":29},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"kind":"identifier("View")","text":"View"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"parent":92,"text":"IdentifierType","type":"type","id":94},{"id":95,"parent":94,"type":"other","range":{"startColumn":25,"startRow":8,"endColumn":29,"endRow":8},"structure":[],"text":"View","token":{"trailingTrivia":"␣<\/span>","kind":"identifier("View")","leadingTrivia":""}},{"range":{"startColumn":30,"startRow":8,"endColumn":4,"endRow":23},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndAccessors"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"accessors"},{"value":{"text":"nil"},"name":"unexpectedBetweenAccessorsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":87,"text":"AccessorBlock","type":"other","id":96},{"type":"other","range":{"startRow":8,"startColumn":30,"endColumn":31,"endRow":8},"structure":[],"id":97,"token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"parent":96,"text":"{"},{"range":{"startRow":9,"startColumn":5,"endColumn":6,"endRow":22},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":96,"text":"CodeBlockItemList","type":"collection","id":98},{"range":{"endRow":22,"startRow":9,"endColumn":6,"startColumn":5},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":98,"text":"CodeBlockItem","type":"other","id":99},{"range":{"endRow":22,"startRow":9,"startColumn":5,"endColumn":6},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"nil"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":"nil"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"ref":"ClosureExprSyntax","value":{"text":"ClosureExprSyntax"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"parent":99,"text":"FunctionCallExpr","type":"expr","id":100},{"range":{"endRow":9,"startRow":9,"startColumn":5,"endColumn":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"HStack","kind":"identifier("HStack")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":100,"text":"DeclReferenceExpr","type":"expr","id":101},{"range":{"endRow":9,"startRow":9,"startColumn":5,"endColumn":11},"structure":[],"text":"HStack","id":102,"type":"other","parent":101,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("HStack")","trailingTrivia":"␣<\/span>"}},{"range":{"endRow":9,"startRow":9,"startColumn":12,"endColumn":12},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":100,"text":"LabeledExprList","type":"collection","id":103},{"range":{"startRow":9,"startColumn":12,"endColumn":6,"endRow":22},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndSignature"},{"value":{"text":"nil"},"name":"signature"},{"value":{"text":"nil"},"name":"unexpectedBetweenSignatureAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":100,"text":"ClosureExpr","type":"expr","id":104},{"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"leftBrace"},"range":{"startColumn":12,"endColumn":13,"endRow":9,"startRow":9},"structure":[],"parent":104,"text":"{","id":105},{"range":{"startColumn":7,"endColumn":8,"endRow":21,"startRow":10},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"2"}}],"parent":104,"text":"CodeBlockItemList","type":"collection","id":106},{"range":{"startRow":10,"endRow":13,"startColumn":7,"endColumn":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"name":"item","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":106,"text":"CodeBlockItem","type":"other","id":107},{"range":{"startColumn":7,"endRow":13,"startRow":10,"endColumn":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"kind":"rightParen","text":")"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"ref":"ClosureExprSyntax","value":{"text":"ClosureExprSyntax"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"parent":107,"text":"FunctionCallExpr","type":"expr","id":108},{"range":{"endRow":10,"endColumn":13,"startColumn":7,"startRow":10},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"Button","kind":"identifier("Button")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":108,"text":"DeclReferenceExpr","type":"expr","id":109},{"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"identifier("Button")"},"parent":109,"type":"other","range":{"startRow":10,"startColumn":7,"endColumn":13,"endRow":10},"id":110,"structure":[],"text":"Button"},{"id":111,"parent":108,"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"leftParen"},"type":"other","text":"(","range":{"startRow":10,"startColumn":13,"endColumn":14,"endRow":10}},{"range":{"startRow":10,"startColumn":14,"endColumn":30,"endRow":10},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":108,"text":"LabeledExprList","type":"collection","id":112},{"range":{"endRow":10,"startRow":10,"startColumn":14,"endColumn":30},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"kind":"identifier("action")","text":"action"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"kind":"colon","text":":"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"expression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":112,"text":"LabeledExpr","type":"other","id":113},{"type":"other","structure":[],"token":{"leadingTrivia":"","trailingTrivia":"","kind":"identifier("action")"},"parent":113,"id":114,"text":"action","range":{"startColumn":14,"endRow":10,"startRow":10,"endColumn":20}},{"structure":[],"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"colon"},"text":":","parent":113,"id":115,"range":{"startColumn":20,"endRow":10,"startRow":10,"endColumn":21},"type":"other"},{"range":{"startColumn":22,"endRow":10,"startRow":10,"endColumn":30},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("onToggle")","text":"onToggle"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":113,"text":"DeclReferenceExpr","type":"expr","id":116},{"structure":[],"type":"other","token":{"leadingTrivia":"","kind":"identifier("onToggle")","trailingTrivia":""},"parent":116,"text":"onToggle","id":117,"range":{"endColumn":30,"startRow":10,"endRow":10,"startColumn":22}},{"range":{"endColumn":31,"startRow":10,"endRow":10,"startColumn":30},"type":"other","token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":"␣<\/span>"},"parent":108,"text":")","id":118,"structure":[]},{"range":{"endColumn":8,"startRow":10,"endRow":13,"startColumn":32},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndSignature"},{"value":{"text":"nil"},"name":"signature"},{"value":{"text":"nil"},"name":"unexpectedBetweenSignatureAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"ref":"CodeBlockItemListSyntax","name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"text":"}","kind":"rightBrace"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":108,"text":"ClosureExpr","type":"expr","id":119},{"type":"other","token":{"kind":"leftBrace","leadingTrivia":"","trailingTrivia":""},"parent":119,"structure":[],"id":120,"text":"{","range":{"startColumn":32,"startRow":10,"endRow":10,"endColumn":33}},{"range":{"startColumn":9,"startRow":11,"endRow":12,"endColumn":62},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":119,"text":"CodeBlockItemList","type":"collection","id":121},{"range":{"endRow":12,"endColumn":62,"startRow":11,"startColumn":9},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":121,"text":"CodeBlockItem","type":"other","id":122},{"range":{"startRow":11,"startColumn":9,"endRow":12,"endColumn":62},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"ref":"MemberAccessExprSyntax","value":{"text":"MemberAccessExprSyntax"},"name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"(","kind":"leftParen"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"nil"},"name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"parent":122,"text":"FunctionCallExpr","type":"expr","id":123},{"range":{"endColumn":27,"startRow":11,"startColumn":9,"endRow":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"FunctionCallExprSyntax"},"name":"base","ref":"FunctionCallExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"declName","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"parent":123,"text":"MemberAccessExpr","type":"expr","id":124},{"range":{"endColumn":81,"endRow":11,"startColumn":9,"startRow":11},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"ref":"LabeledExprListSyntax","name":"arguments","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"parent":124,"text":"FunctionCallExpr","type":"expr","id":125},{"range":{"startColumn":9,"startRow":11,"endRow":11,"endColumn":14},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"Image","kind":"identifier("Image")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":125,"text":"DeclReferenceExpr","type":"expr","id":126},{"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"identifier("Image")","trailingTrivia":""},"id":127,"parent":126,"text":"Image","structure":[],"type":"other","range":{"startRow":11,"startColumn":9,"endRow":11,"endColumn":14}},{"parent":125,"structure":[],"type":"other","id":128,"range":{"startRow":11,"startColumn":14,"endRow":11,"endColumn":15},"text":"(","token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""}},{"range":{"startRow":11,"startColumn":15,"endRow":11,"endColumn":80},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":125,"text":"LabeledExprList","type":"collection","id":129},{"range":{"endRow":11,"startColumn":15,"endColumn":80,"startRow":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"kind":"identifier("systemName")","text":"systemName"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"TernaryExprSyntax"},"ref":"TernaryExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":129,"text":"LabeledExpr","type":"other","id":130},{"parent":130,"type":"other","token":{"leadingTrivia":"","kind":"identifier("systemName")","trailingTrivia":""},"id":131,"structure":[],"range":{"endColumn":25,"startRow":11,"startColumn":15,"endRow":11},"text":"systemName"},{"range":{"endColumn":26,"startRow":11,"startColumn":25,"endRow":11},"id":132,"parent":130,"text":":","type":"other","structure":[],"token":{"leadingTrivia":"","kind":"colon","trailingTrivia":"␣<\/span>"}},{"range":{"endColumn":80,"startRow":11,"startColumn":27,"endRow":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"value":{"text":"MemberAccessExprSyntax"},"name":"condition","ref":"MemberAccessExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndQuestionMark"},{"value":{"text":"?","kind":"infixQuestionMark"},"name":"questionMark"},{"value":{"text":"nil"},"name":"unexpectedBetweenQuestionMarkAndThenExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"thenExpression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenThenExpressionAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndElseExpression"},{"value":{"text":"StringLiteralExprSyntax"},"name":"elseExpression","ref":"StringLiteralExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterElseExpression"}],"parent":130,"text":"TernaryExpr","type":"expr","id":133},{"range":{"endRow":11,"startRow":11,"startColumn":27,"endColumn":43},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBase"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"base","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseAndPeriod"},{"value":{"text":".","kind":"period"},"name":"period"},{"value":{"text":"nil"},"name":"unexpectedBetweenPeriodAndDeclName"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"declName","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterDeclName"}],"parent":133,"text":"MemberAccessExpr","type":"expr","id":134},{"range":{"endColumn":31,"startRow":11,"startColumn":27,"endRow":11},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"item","kind":"identifier("item")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":134,"text":"DeclReferenceExpr","type":"expr","id":135},{"range":{"startColumn":27,"endRow":11,"startRow":11,"endColumn":31},"structure":[],"text":"item","parent":135,"type":"other","id":136,"token":{"trailingTrivia":"","kind":"identifier("item")","leadingTrivia":""}},{"text":".","range":{"startColumn":31,"endRow":11,"startRow":11,"endColumn":32},"parent":134,"id":137,"type":"other","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"structure":[]},{"range":{"startColumn":32,"endRow":11,"startRow":11,"endColumn":43},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"isCompleted","kind":"identifier("isCompleted")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":134,"text":"DeclReferenceExpr","type":"expr","id":138},{"text":"isCompleted","type":"other","structure":[],"parent":138,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"identifier("isCompleted")"},"range":{"endRow":11,"startRow":11,"endColumn":43,"startColumn":32},"id":139},{"range":{"endRow":11,"startRow":11,"endColumn":45,"startColumn":44},"text":"?","id":140,"token":{"leadingTrivia":"","trailingTrivia":"␣<\/span>","kind":"infixQuestionMark"},"parent":133,"type":"other","structure":[]},{"range":{"endRow":11,"startRow":11,"endColumn":69,"startColumn":46},"structure":[{"name":"unexpectedBeforeOpeningPounds","value":{"text":"nil"}},{"name":"openingPounds","value":{"text":"nil"}},{"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote","value":{"text":"nil"}},{"name":"openingQuote","value":{"text":""","kind":"stringQuote"}},{"name":"unexpectedBetweenOpeningQuoteAndSegments","value":{"text":"nil"}},{"name":"segments","ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"}},{"name":"unexpectedBetweenSegmentsAndClosingQuote","value":{"text":"nil"}},{"name":"closingQuote","value":{"kind":"stringQuote","text":"""}},{"name":"unexpectedBetweenClosingQuoteAndClosingPounds","value":{"text":"nil"}},{"name":"closingPounds","value":{"text":"nil"}},{"name":"unexpectedAfterClosingPounds","value":{"text":"nil"}}],"parent":133,"text":"StringLiteralExpr","type":"expr","id":141},{"id":142,"token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"type":"other","structure":[],"parent":141,"text":""","range":{"endRow":11,"startColumn":46,"endColumn":47,"startRow":11}},{"range":{"endRow":11,"startColumn":47,"endColumn":68,"startRow":11},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":141,"text":"StringLiteralSegmentList","type":"collection","id":143},{"range":{"endColumn":68,"startColumn":47,"startRow":11,"endRow":11},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"text":"checkmark.circle.fill","kind":"stringSegment("checkmark.circle.fill")"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"parent":143,"text":"StringSegment","type":"other","id":144},{"range":{"endRow":11,"endColumn":68,"startRow":11,"startColumn":47},"id":145,"parent":144,"structure":[],"type":"other","token":{"trailingTrivia":"","kind":"stringSegment("checkmark.circle.fill")","leadingTrivia":""},"text":"checkmark.circle.fill"},{"id":146,"token":{"trailingTrivia":"␣<\/span>","kind":"stringQuote","leadingTrivia":""},"range":{"endRow":11,"endColumn":69,"startRow":11,"startColumn":68},"text":""","parent":141,"type":"other","structure":[]},{"type":"other","range":{"endRow":11,"endColumn":71,"startRow":11,"startColumn":70},"id":147,"structure":[],"parent":133,"token":{"trailingTrivia":"␣<\/span>","kind":"colon","leadingTrivia":""},"text":":"},{"range":{"endRow":11,"endColumn":80,"startRow":11,"startColumn":72},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"text":""","kind":"stringQuote"},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"value":{"text":"StringLiteralSegmentListSyntax"},"ref":"StringLiteralSegmentListSyntax","name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"parent":133,"text":"StringLiteralExpr","type":"expr","id":148},{"text":""","token":{"leadingTrivia":"","kind":"stringQuote","trailingTrivia":""},"structure":[],"range":{"startColumn":72,"endRow":11,"startRow":11,"endColumn":73},"parent":148,"id":149,"type":"other"},{"range":{"startColumn":73,"endRow":11,"startRow":11,"endColumn":79},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"parent":148,"text":"StringLiteralSegmentList","type":"collection","id":150},{"range":{"startColumn":73,"startRow":11,"endColumn":79,"endRow":11},"structure":[{"name":"unexpectedBeforeContent","value":{"text":"nil"}},{"name":"content","value":{"kind":"stringSegment("circle")","text":"circle"}},{"name":"unexpectedAfterContent","value":{"text":"nil"}}],"parent":150,"text":"StringSegment","type":"other","id":151},{"range":{"startRow":11,"startColumn":73,"endRow":11,"endColumn":79},"text":"circle","type":"other","structure":[],"parent":151,"id":152,"token":{"kind":"stringSegment("circle")","trailingTrivia":"","leadingTrivia":""}},{"range":{"startRow":11,"startColumn":79,"endRow":11,"endColumn":80},"token":{"kind":"stringQuote","trailingTrivia":"","leadingTrivia":""},"id":153,"type":"other","text":""","structure":[],"parent":148},{"text":")","type":"other","parent":125,"id":154,"range":{"startRow":11,"startColumn":80,"endRow":11,"endColumn":81},"structure":[],"token":{"kind":"rightParen","trailingTrivia":"","leadingTrivia":""}},{"range":{"startRow":11,"startColumn":81,"endRow":11,"endColumn":81},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":125,"text":"MultipleTrailingClosureElementList","type":"collection","id":155},{"type":"other","text":".","range":{"startColumn":11,"endRow":12,"startRow":12,"endColumn":12},"structure":[],"id":156,"token":{"trailingTrivia":"","kind":"period","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"parent":124},{"range":{"startColumn":12,"endRow":12,"startRow":12,"endColumn":27},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("foregroundColor")","text":"foregroundColor"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":124,"text":"DeclReferenceExpr","type":"expr","id":157},{"id":158,"type":"other","parent":157,"text":"foregroundColor","token":{"kind":"identifier("foregroundColor")","leadingTrivia":"","trailingTrivia":""},"structure":[],"range":{"startRow":12,"startColumn":12,"endColumn":27,"endRow":12}},{"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":12,"startColumn":27,"endColumn":28,"endRow":12},"parent":123,"text":"(","id":159,"type":"other","structure":[]},{"range":{"startRow":12,"startColumn":28,"endColumn":61,"endRow":12},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":123,"text":"LabeledExprList","type":"collection","id":160},{"range":{"startColumn":28,"endRow":12,"startRow":12,"endColumn":61},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"nil"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":"nil"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"TernaryExprSyntax"},"ref":"TernaryExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":160,"text":"LabeledExpr","type":"other","id":161},{"range":{"endRow":12,"endColumn":61,"startColumn":28,"startRow":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCondition"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"condition"},{"value":{"text":"nil"},"name":"unexpectedBetweenConditionAndQuestionMark"},{"value":{"kind":"infixQuestionMark","text":"?"},"name":"questionMark"},{"value":{"text":"nil"},"name":"unexpectedBetweenQuestionMarkAndThenExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"thenExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenThenExpressionAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndElseExpression"},{"value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax","name":"elseExpression"},{"value":{"text":"nil"},"name":"unexpectedAfterElseExpression"}],"parent":161,"text":"TernaryExpr","type":"expr","id":162},{"range":{"endRow":12,"startRow":12,"startColumn":28,"endColumn":44},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"parent":162,"text":"MemberAccessExpr","type":"expr","id":163},{"range":{"startRow":12,"startColumn":28,"endColumn":32,"endRow":12},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("item")","text":"item"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":163,"text":"DeclReferenceExpr","type":"expr","id":164},{"id":165,"text":"item","token":{"trailingTrivia":"","kind":"identifier("item")","leadingTrivia":""},"parent":164,"range":{"startColumn":28,"startRow":12,"endRow":12,"endColumn":32},"structure":[],"type":"other"},{"id":166,"type":"other","structure":[],"text":".","token":{"trailingTrivia":"","kind":"period","leadingTrivia":""},"parent":163,"range":{"startColumn":32,"startRow":12,"endRow":12,"endColumn":33}},{"range":{"startColumn":33,"startRow":12,"endRow":12,"endColumn":44},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("isCompleted")","text":"isCompleted"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":163,"text":"DeclReferenceExpr","type":"expr","id":167},{"type":"other","token":{"leadingTrivia":"","kind":"identifier("isCompleted")","trailingTrivia":"␣<\/span>"},"structure":[],"text":"isCompleted","range":{"endRow":12,"startRow":12,"endColumn":44,"startColumn":33},"parent":167,"id":168},{"parent":162,"range":{"endRow":12,"startRow":12,"endColumn":46,"startColumn":45},"type":"other","structure":[],"id":169,"token":{"leadingTrivia":"","kind":"infixQuestionMark","trailingTrivia":"␣<\/span>"},"text":"?"},{"range":{"endRow":12,"startRow":12,"endColumn":53,"startColumn":47},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"nil"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"parent":162,"text":"MemberAccessExpr","type":"expr","id":170},{"text":".","token":{"leadingTrivia":"","trailingTrivia":"","kind":"period"},"type":"other","parent":170,"range":{"endRow":12,"startRow":12,"endColumn":48,"startColumn":47},"id":171,"structure":[]},{"range":{"endRow":12,"startRow":12,"endColumn":53,"startColumn":48},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"green","kind":"identifier("green")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":170,"text":"DeclReferenceExpr","type":"expr","id":172},{"structure":[],"type":"other","id":173,"text":"green","parent":172,"range":{"startRow":12,"startColumn":48,"endRow":12,"endColumn":53},"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"identifier("green")"}},{"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"colon"},"id":174,"range":{"startRow":12,"startColumn":54,"endRow":12,"endColumn":55},"structure":[],"parent":162,"text":":","type":"other"},{"range":{"startRow":12,"startColumn":56,"endRow":12,"endColumn":61},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"name":"base","value":{"text":"nil"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"text":".","kind":"period"}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"name":"declName","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"parent":162,"text":"MemberAccessExpr","type":"expr","id":175},{"token":{"kind":"period","trailingTrivia":"","leadingTrivia":""},"text":".","type":"other","range":{"endColumn":57,"startColumn":56,"startRow":12,"endRow":12},"structure":[],"id":176,"parent":175},{"range":{"endColumn":61,"startColumn":57,"startRow":12,"endRow":12},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"gray","kind":"identifier("gray")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":175,"text":"DeclReferenceExpr","type":"expr","id":177},{"structure":[],"range":{"startRow":12,"endRow":12,"startColumn":57,"endColumn":61},"token":{"kind":"identifier("gray")","leadingTrivia":"","trailingTrivia":""},"parent":177,"type":"other","id":178,"text":"gray"},{"id":179,"text":")","parent":123,"structure":[],"type":"other","token":{"kind":"rightParen","leadingTrivia":"","trailingTrivia":""},"range":{"startRow":12,"endRow":12,"startColumn":61,"endColumn":62}},{"range":{"startRow":12,"endRow":12,"startColumn":62,"endColumn":62},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":123,"text":"MultipleTrailingClosureElementList","type":"collection","id":180},{"type":"other","structure":[],"parent":119,"range":{"startRow":13,"endRow":13,"endColumn":8,"startColumn":7},"text":"}","id":181,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"rightBrace","trailingTrivia":""}},{"range":{"startRow":13,"endRow":13,"endColumn":8,"startColumn":8},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":108,"text":"MultipleTrailingClosureElementList","type":"collection","id":182},{"range":{"startColumn":7,"startRow":15,"endRow":21,"endColumn":8},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax","name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":106,"text":"CodeBlockItem","type":"other","id":183},{"range":{"startRow":15,"endColumn":8,"startColumn":7,"endRow":21},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"name":"calledExpression","ref":"DeclReferenceExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"kind":"leftParen","text":"("},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"name":"arguments","ref":"LabeledExprListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":")","kind":"rightParen"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"ClosureExprSyntax"},"name":"trailingClosure","ref":"ClosureExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"parent":183,"text":"FunctionCallExpr","type":"expr","id":184},{"range":{"startColumn":7,"endRow":15,"startRow":15,"endColumn":13},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"kind":"identifier("Button")","text":"Button"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":184,"text":"DeclReferenceExpr","type":"expr","id":185},{"text":"Button","parent":185,"structure":[],"range":{"startRow":15,"startColumn":7,"endRow":15,"endColumn":13},"id":186,"token":{"kind":"identifier("Button")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"type":"other"},{"structure":[],"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"parent":184,"range":{"startRow":15,"startColumn":13,"endRow":15,"endColumn":14},"id":187,"text":"(","type":"other"},{"range":{"startRow":15,"startColumn":14,"endRow":19,"endColumn":8},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":184,"text":"LabeledExprList","type":"collection","id":188},{"range":{"startColumn":14,"endRow":19,"endColumn":8,"startRow":15},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"action","kind":"identifier("action")"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"ClosureExprSyntax"},"name":"expression","ref":"ClosureExprSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":188,"text":"LabeledExpr","type":"other","id":189},{"type":"other","range":{"startRow":15,"endColumn":20,"startColumn":14,"endRow":15},"text":"action","structure":[],"id":190,"token":{"kind":"identifier("action")","leadingTrivia":"","trailingTrivia":""},"parent":189},{"structure":[],"type":"other","parent":189,"text":":","id":191,"token":{"kind":"colon","leadingTrivia":"","trailingTrivia":"␣<\/span>"},"range":{"startRow":15,"endColumn":21,"startColumn":20,"endRow":15}},{"range":{"startRow":15,"endColumn":8,"startColumn":22,"endRow":19},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"kind":"leftBrace","text":"{"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndSignature"},{"value":{"text":"nil"},"name":"signature"},{"value":{"text":"nil"},"name":"unexpectedBetweenSignatureAndStatements"},{"ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"},"name":"statements"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":189,"text":"ClosureExpr","type":"expr","id":192},{"token":{"kind":"leftBrace","trailingTrivia":"","leadingTrivia":""},"structure":[],"range":{"endColumn":23,"endRow":15,"startColumn":22,"startRow":15},"parent":192,"text":"{","id":193,"type":"other"},{"range":{"endColumn":10,"endRow":18,"startColumn":9,"startRow":16},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":192,"text":"CodeBlockItemList","type":"collection","id":194},{"range":{"startRow":16,"startColumn":9,"endRow":18,"endColumn":10},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"ref":"FunctionCallExprSyntax","name":"item","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":194,"text":"CodeBlockItem","type":"other","id":195},{"range":{"startRow":16,"startColumn":9,"endColumn":10,"endRow":18},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeCalledExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"calledExpression"},{"value":{"text":"nil"},"name":"unexpectedBetweenCalledExpressionAndLeftParen"},{"value":{"text":"nil"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax","name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":"nil"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenRightParenAndTrailingClosure"},{"value":{"text":"ClosureExprSyntax"},"ref":"ClosureExprSyntax","name":"trailingClosure"},{"value":{"text":"nil"},"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures"},{"value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax","name":"additionalTrailingClosures"},{"value":{"text":"nil"},"name":"unexpectedAfterAdditionalTrailingClosures"}],"parent":195,"text":"FunctionCallExpr","type":"expr","id":196},{"range":{"startColumn":9,"startRow":16,"endRow":16,"endColumn":13},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"Task","kind":"identifier("Task")"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":196,"text":"DeclReferenceExpr","type":"expr","id":197},{"parent":197,"id":198,"type":"other","token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"␣<\/span>","kind":"identifier("Task")"},"range":{"startColumn":9,"endRow":16,"endColumn":13,"startRow":16},"text":"Task","structure":[]},{"range":{"startColumn":14,"endRow":16,"endColumn":14,"startRow":16},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":196,"text":"LabeledExprList","type":"collection","id":199},{"range":{"endColumn":10,"endRow":18,"startRow":16,"startColumn":14},"structure":[{"name":"unexpectedBeforeLeftBrace","value":{"text":"nil"}},{"name":"leftBrace","value":{"kind":"leftBrace","text":"{"}},{"name":"unexpectedBetweenLeftBraceAndSignature","value":{"text":"nil"}},{"name":"signature","ref":"ClosureSignatureSyntax","value":{"text":"ClosureSignatureSyntax"}},{"name":"unexpectedBetweenSignatureAndStatements","value":{"text":"nil"}},{"name":"statements","ref":"CodeBlockItemListSyntax","value":{"text":"CodeBlockItemListSyntax"}},{"name":"unexpectedBetweenStatementsAndRightBrace","value":{"text":"nil"}},{"name":"rightBrace","value":{"text":"}","kind":"rightBrace"}},{"name":"unexpectedAfterRightBrace","value":{"text":"nil"}}],"parent":196,"text":"ClosureExpr","type":"expr","id":200},{"structure":[],"parent":200,"type":"other","range":{"startRow":16,"endRow":16,"startColumn":14,"endColumn":15},"id":201,"token":{"trailingTrivia":"␣<\/span>","kind":"leftBrace","leadingTrivia":""},"text":"{"},{"range":{"startRow":16,"endRow":16,"startColumn":16,"endColumn":41},"structure":[{"name":"unexpectedBeforeAttributes","value":{"text":"nil"}},{"name":"attributes","value":{"text":"AttributeListSyntax"},"ref":"AttributeListSyntax"},{"name":"unexpectedBetweenAttributesAndCapture","value":{"text":"nil"}},{"name":"capture","value":{"text":"ClosureCaptureClauseSyntax"},"ref":"ClosureCaptureClauseSyntax"},{"name":"unexpectedBetweenCaptureAndParameterClause","value":{"text":"nil"}},{"name":"parameterClause","value":{"text":"nil"}},{"name":"unexpectedBetweenParameterClauseAndEffectSpecifiers","value":{"text":"nil"}},{"name":"effectSpecifiers","value":{"text":"nil"}},{"name":"unexpectedBetweenEffectSpecifiersAndReturnClause","value":{"text":"nil"}},{"name":"returnClause","value":{"text":"nil"}},{"name":"unexpectedBetweenReturnClauseAndInKeyword","value":{"text":"nil"}},{"name":"inKeyword","value":{"kind":"keyword(SwiftSyntax.Keyword.in)","text":"in"}},{"name":"unexpectedAfterInKeyword","value":{"text":"nil"}}],"parent":200,"text":"ClosureSignature","type":"other","id":202},{"range":{"startColumn":16,"endRow":16,"startRow":16,"endColumn":26},"structure":[{"name":"Element","value":{"text":"Element"}},{"name":"Count","value":{"text":"1"}}],"parent":202,"text":"AttributeList","type":"collection","id":203},{"range":{"startRow":16,"startColumn":16,"endRow":16,"endColumn":26},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeAtSign"},{"value":{"kind":"atSign","text":"@"},"name":"atSign"},{"value":{"text":"nil"},"name":"unexpectedBetweenAtSignAndAttributeName"},{"ref":"IdentifierTypeSyntax","value":{"text":"IdentifierTypeSyntax"},"name":"attributeName"},{"value":{"text":"nil"},"name":"unexpectedBetweenAttributeNameAndLeftParen"},{"value":{"text":"nil"},"name":"leftParen"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftParenAndArguments"},{"value":{"text":"nil"},"name":"arguments"},{"value":{"text":"nil"},"name":"unexpectedBetweenArgumentsAndRightParen"},{"value":{"text":"nil"},"name":"rightParen"},{"value":{"text":"nil"},"name":"unexpectedAfterRightParen"}],"parent":203,"text":"Attribute","type":"other","id":204},{"structure":[],"text":"@","range":{"endColumn":17,"startRow":16,"endRow":16,"startColumn":16},"parent":204,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"atSign"},"id":205},{"range":{"endColumn":26,"startRow":16,"endRow":16,"startColumn":17},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeName"},{"value":{"text":"MainActor","kind":"identifier("MainActor")"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndGenericArgumentClause"},{"value":{"text":"nil"},"name":"genericArgumentClause"},{"value":{"text":"nil"},"name":"unexpectedAfterGenericArgumentClause"}],"parent":204,"text":"IdentifierType","type":"type","id":206},{"token":{"kind":"identifier("MainActor")","trailingTrivia":"␣<\/span>","leadingTrivia":""},"parent":206,"range":{"startRow":16,"startColumn":17,"endRow":16,"endColumn":26},"type":"other","id":207,"structure":[],"text":"MainActor"},{"range":{"startRow":16,"startColumn":27,"endRow":16,"endColumn":38},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftSquare"},{"value":{"kind":"leftSquare","text":"["},"name":"leftSquare"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftSquareAndItems"},{"value":{"text":"ClosureCaptureListSyntax"},"ref":"ClosureCaptureListSyntax","name":"items"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemsAndRightSquare"},{"value":{"text":"]","kind":"rightSquare"},"name":"rightSquare"},{"value":{"text":"nil"},"name":"unexpectedAfterRightSquare"}],"parent":202,"text":"ClosureCaptureClause","type":"other","id":208},{"structure":[],"parent":208,"range":{"endRow":16,"endColumn":28,"startColumn":27,"startRow":16},"text":"[","token":{"kind":"leftSquare","leadingTrivia":"","trailingTrivia":""},"type":"other","id":209},{"range":{"endRow":16,"endColumn":37,"startColumn":28,"startRow":16},"structure":[{"name":"Element","value":{"text":"ClosureCaptureSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":208,"text":"ClosureCaptureList","type":"collection","id":210},{"range":{"endColumn":37,"startRow":16,"endRow":16,"startColumn":28},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeSpecifier"},{"value":{"text":"ClosureCaptureSpecifierSyntax"},"name":"specifier","ref":"ClosureCaptureSpecifierSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenSpecifierAndName"},{"value":{"text":"self","kind":"keyword(SwiftSyntax.Keyword.self)"},"name":"name"},{"value":{"text":"nil"},"name":"unexpectedBetweenNameAndInitializer"},{"value":{"text":"nil"},"name":"initializer"},{"value":{"text":"nil"},"name":"unexpectedBetweenInitializerAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":210,"text":"ClosureCapture","type":"other","id":211},{"range":{"startRow":16,"endRow":16,"startColumn":28,"endColumn":32},"structure":[{"name":"unexpectedBeforeSpecifier","value":{"text":"nil"}},{"name":"specifier","value":{"kind":"keyword(SwiftSyntax.Keyword.weak)","text":"weak"}},{"name":"unexpectedBetweenSpecifierAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"nil"}},{"name":"unexpectedBetweenLeftParenAndDetail","value":{"text":"nil"}},{"name":"detail","value":{"text":"nil"}},{"name":"unexpectedBetweenDetailAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":"nil"}},{"name":"unexpectedAfterRightParen","value":{"text":"nil"}}],"parent":211,"text":"ClosureCaptureSpecifier","type":"other","id":212},{"id":213,"parent":212,"structure":[],"text":"weak","type":"other","token":{"kind":"keyword(SwiftSyntax.Keyword.weak)","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"startRow":16,"endColumn":32,"startColumn":28,"endRow":16}},{"structure":[],"type":"other","parent":211,"text":"self","id":214,"token":{"kind":"keyword(SwiftSyntax.Keyword.self)","trailingTrivia":"","leadingTrivia":""},"range":{"startRow":16,"endColumn":37,"startColumn":33,"endRow":16}},{"structure":[],"text":"]","token":{"kind":"rightSquare","trailingTrivia":"␣<\/span>","leadingTrivia":""},"range":{"startRow":16,"endColumn":38,"startColumn":37,"endRow":16},"id":215,"parent":208,"type":"other"},{"id":216,"structure":[],"parent":202,"text":"in","token":{"kind":"keyword(SwiftSyntax.Keyword.in)","trailingTrivia":"","leadingTrivia":""},"type":"other","range":{"startRow":16,"endColumn":41,"startColumn":39,"endRow":16}},{"range":{"startRow":17,"endColumn":33,"startColumn":11,"endRow":17},"structure":[{"name":"Element","value":{"text":"CodeBlockItemSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":200,"text":"CodeBlockItemList","type":"collection","id":217},{"range":{"endRow":17,"endColumn":33,"startRow":17,"startColumn":11},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeItem"},{"ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"},"name":"item"},{"value":{"text":"nil"},"name":"unexpectedBetweenItemAndSemicolon"},{"value":{"text":"nil"},"name":"semicolon"},{"value":{"text":"nil"},"name":"unexpectedAfterSemicolon"}],"parent":217,"text":"CodeBlockItem","type":"other","id":218},{"range":{"startRow":17,"startColumn":11,"endRow":17,"endColumn":33},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"MemberAccessExprSyntax"},"ref":"MemberAccessExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"parent":218,"text":"FunctionCallExpr","type":"expr","id":219},{"range":{"startColumn":11,"startRow":17,"endRow":17,"endColumn":25},"structure":[{"name":"unexpectedBeforeBase","value":{"text":"nil"}},{"ref":"OptionalChainingExprSyntax","name":"base","value":{"text":"OptionalChainingExprSyntax"}},{"name":"unexpectedBetweenBaseAndPeriod","value":{"text":"nil"}},{"name":"period","value":{"kind":"period","text":"."}},{"name":"unexpectedBetweenPeriodAndDeclName","value":{"text":"nil"}},{"ref":"DeclReferenceExprSyntax","name":"declName","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedAfterDeclName","value":{"text":"nil"}}],"parent":219,"text":"MemberAccessExpr","type":"expr","id":220},{"range":{"endRow":17,"endColumn":16,"startColumn":11,"startRow":17},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeExpression"},{"value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndQuestionMark"},{"value":{"kind":"postfixQuestionMark","text":"?"},"name":"questionMark"},{"value":{"text":"nil"},"name":"unexpectedAfterQuestionMark"}],"parent":220,"text":"OptionalChainingExpr","type":"expr","id":221},{"range":{"startRow":17,"endColumn":15,"startColumn":11,"endRow":17},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"text":"self","kind":"keyword(SwiftSyntax.Keyword.self)"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":221,"text":"DeclReferenceExpr","type":"expr","id":222},{"range":{"startColumn":11,"endRow":17,"startRow":17,"endColumn":15},"structure":[],"parent":222,"id":223,"text":"self","token":{"kind":"keyword(SwiftSyntax.Keyword.self)","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"type":"other"},{"id":224,"parent":221,"range":{"startColumn":15,"endRow":17,"startRow":17,"endColumn":16},"type":"other","token":{"kind":"postfixQuestionMark","leadingTrivia":"","trailingTrivia":""},"structure":[],"text":"?"},{"type":"other","parent":220,"structure":[],"text":".","id":225,"token":{"kind":"period","leadingTrivia":"","trailingTrivia":""},"range":{"startColumn":16,"endRow":17,"startRow":17,"endColumn":17}},{"range":{"startColumn":17,"endRow":17,"startRow":17,"endColumn":25},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"onToggle","kind":"identifier("onToggle")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":220,"text":"DeclReferenceExpr","type":"expr","id":226},{"range":{"endRow":17,"endColumn":25,"startRow":17,"startColumn":17},"structure":[],"type":"other","text":"onToggle","id":227,"token":{"leadingTrivia":"","kind":"identifier("onToggle")","trailingTrivia":""},"parent":226},{"structure":[],"parent":219,"range":{"endRow":17,"endColumn":26,"startRow":17,"startColumn":25},"type":"other","id":228,"token":{"leadingTrivia":"","kind":"leftParen","trailingTrivia":""},"text":"("},{"range":{"endRow":17,"endColumn":32,"startRow":17,"startColumn":26},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"1"}}],"parent":219,"text":"LabeledExprList","type":"collection","id":229},{"range":{"startRow":17,"endRow":17,"startColumn":26,"endColumn":32},"structure":[{"name":"unexpectedBeforeLabel","value":{"text":"nil"}},{"name":"label","value":{"text":"nil"}},{"name":"unexpectedBetweenLabelAndColon","value":{"text":"nil"}},{"name":"colon","value":{"text":"nil"}},{"name":"unexpectedBetweenColonAndExpression","value":{"text":"nil"}},{"name":"expression","ref":"FunctionCallExprSyntax","value":{"text":"FunctionCallExprSyntax"}},{"name":"unexpectedBetweenExpressionAndTrailingComma","value":{"text":"nil"}},{"name":"trailingComma","value":{"text":"nil"}},{"name":"unexpectedAfterTrailingComma","value":{"text":"nil"}}],"parent":229,"text":"LabeledExpr","type":"other","id":230},{"range":{"startColumn":26,"endRow":17,"startRow":17,"endColumn":32},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","ref":"DeclReferenceExprSyntax","value":{"text":"DeclReferenceExprSyntax"}},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"text":"(","kind":"leftParen"}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","ref":"LabeledExprListSyntax","value":{"text":"LabeledExprListSyntax"}},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"text":")","kind":"rightParen"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","ref":"MultipleTrailingClosureElementListSyntax","value":{"text":"MultipleTrailingClosureElementListSyntax"}},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"parent":230,"text":"FunctionCallExpr","type":"expr","id":231},{"range":{"endRow":17,"startRow":17,"startColumn":26,"endColumn":30},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeBaseName"},{"value":{"text":"Date","kind":"identifier("Date")"},"name":"baseName"},{"value":{"text":"nil"},"name":"unexpectedBetweenBaseNameAndArgumentNames"},{"value":{"text":"nil"},"name":"argumentNames"},{"value":{"text":"nil"},"name":"unexpectedAfterArgumentNames"}],"parent":231,"text":"DeclReferenceExpr","type":"expr","id":232},{"id":233,"structure":[],"type":"other","token":{"trailingTrivia":"","kind":"identifier("Date")","leadingTrivia":""},"range":{"startRow":17,"endRow":17,"startColumn":26,"endColumn":30},"parent":232,"text":"Date"},{"range":{"startRow":17,"endRow":17,"startColumn":30,"endColumn":31},"parent":231,"text":"(","token":{"trailingTrivia":"","kind":"leftParen","leadingTrivia":""},"id":234,"structure":[],"type":"other"},{"range":{"startRow":17,"endRow":17,"startColumn":31,"endColumn":31},"structure":[{"name":"Element","value":{"text":"LabeledExprSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":231,"text":"LabeledExprList","type":"collection","id":235},{"id":236,"token":{"leadingTrivia":"","kind":"rightParen","trailingTrivia":""},"parent":231,"structure":[],"range":{"startRow":17,"endRow":17,"endColumn":32,"startColumn":31},"type":"other","text":")"},{"range":{"startRow":17,"endRow":17,"endColumn":32,"startColumn":32},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":231,"text":"MultipleTrailingClosureElementList","type":"collection","id":237},{"structure":[],"parent":219,"range":{"endRow":17,"startColumn":32,"startRow":17,"endColumn":33},"type":"other","id":238,"text":")","token":{"leadingTrivia":"","trailingTrivia":"","kind":"rightParen"}},{"range":{"endRow":17,"startColumn":33,"startRow":17,"endColumn":33},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":219,"text":"MultipleTrailingClosureElementList","type":"collection","id":239},{"range":{"endRow":18,"startRow":18,"startColumn":9,"endColumn":10},"id":240,"structure":[],"text":"}","parent":200,"type":"other","token":{"trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","kind":"rightBrace"}},{"range":{"endRow":18,"startRow":18,"startColumn":10,"endColumn":10},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":196,"text":"MultipleTrailingClosureElementList","type":"collection","id":241},{"structure":[],"parent":192,"type":"other","id":242,"token":{"kind":"rightBrace","trailingTrivia":"","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>"},"range":{"startRow":19,"endColumn":8,"startColumn":7,"endRow":19},"text":"}"},{"structure":[],"text":")","parent":184,"range":{"startRow":19,"endColumn":9,"startColumn":8,"endRow":19},"type":"other","id":243,"token":{"kind":"rightParen","trailingTrivia":"␣<\/span>","leadingTrivia":""}},{"range":{"startRow":19,"endColumn":8,"startColumn":10,"endRow":21},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLeftBrace"},{"value":{"text":"{","kind":"leftBrace"},"name":"leftBrace"},{"value":{"text":"nil"},"name":"unexpectedBetweenLeftBraceAndSignature"},{"value":{"text":"nil"},"name":"signature"},{"value":{"text":"nil"},"name":"unexpectedBetweenSignatureAndStatements"},{"value":{"text":"CodeBlockItemListSyntax"},"name":"statements","ref":"CodeBlockItemListSyntax"},{"value":{"text":"nil"},"name":"unexpectedBetweenStatementsAndRightBrace"},{"value":{"kind":"rightBrace","text":"}"},"name":"rightBrace"},{"value":{"text":"nil"},"name":"unexpectedAfterRightBrace"}],"parent":184,"text":"ClosureExpr","type":"expr","id":244},{"token":{"kind":"leftBrace","trailingTrivia":"","leadingTrivia":""},"text":"{","range":{"startRow":19,"endColumn":11,"endRow":19,"startColumn":10},"id":245,"structure":[],"type":"other","parent":244},{"range":{"startRow":20,"endColumn":35,"endRow":20,"startColumn":9},"structure":[{"value":{"text":"CodeBlockItemSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":244,"text":"CodeBlockItemList","type":"collection","id":246},{"range":{"startColumn":9,"startRow":20,"endColumn":35,"endRow":20},"structure":[{"name":"unexpectedBeforeItem","value":{"text":"nil"}},{"name":"item","value":{"text":"FunctionCallExprSyntax"},"ref":"FunctionCallExprSyntax"},{"name":"unexpectedBetweenItemAndSemicolon","value":{"text":"nil"}},{"name":"semicolon","value":{"text":"nil"}},{"name":"unexpectedAfterSemicolon","value":{"text":"nil"}}],"parent":246,"text":"CodeBlockItem","type":"other","id":247},{"range":{"startRow":20,"endColumn":35,"endRow":20,"startColumn":9},"structure":[{"name":"unexpectedBeforeCalledExpression","value":{"text":"nil"}},{"name":"calledExpression","value":{"text":"DeclReferenceExprSyntax"},"ref":"DeclReferenceExprSyntax"},{"name":"unexpectedBetweenCalledExpressionAndLeftParen","value":{"text":"nil"}},{"name":"leftParen","value":{"kind":"leftParen","text":"("}},{"name":"unexpectedBetweenLeftParenAndArguments","value":{"text":"nil"}},{"name":"arguments","value":{"text":"LabeledExprListSyntax"},"ref":"LabeledExprListSyntax"},{"name":"unexpectedBetweenArgumentsAndRightParen","value":{"text":"nil"}},{"name":"rightParen","value":{"kind":"rightParen","text":")"}},{"name":"unexpectedBetweenRightParenAndTrailingClosure","value":{"text":"nil"}},{"name":"trailingClosure","value":{"text":"nil"}},{"name":"unexpectedBetweenTrailingClosureAndAdditionalTrailingClosures","value":{"text":"nil"}},{"name":"additionalTrailingClosures","value":{"text":"MultipleTrailingClosureElementListSyntax"},"ref":"MultipleTrailingClosureElementListSyntax"},{"name":"unexpectedAfterAdditionalTrailingClosures","value":{"text":"nil"}}],"parent":247,"text":"FunctionCallExpr","type":"expr","id":248},{"range":{"startColumn":9,"endRow":20,"endColumn":14,"startRow":20},"structure":[{"name":"unexpectedBeforeBaseName","value":{"text":"nil"}},{"name":"baseName","value":{"kind":"identifier("Image")","text":"Image"}},{"name":"unexpectedBetweenBaseNameAndArgumentNames","value":{"text":"nil"}},{"name":"argumentNames","value":{"text":"nil"}},{"name":"unexpectedAfterArgumentNames","value":{"text":"nil"}}],"parent":248,"text":"DeclReferenceExpr","type":"expr","id":249},{"structure":[],"parent":249,"token":{"kind":"identifier("Image")","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"text":"Image","type":"other","range":{"endRow":20,"endColumn":14,"startRow":20,"startColumn":9},"id":250},{"type":"other","text":"(","parent":248,"structure":[],"id":251,"token":{"kind":"leftParen","leadingTrivia":"","trailingTrivia":""},"range":{"endRow":20,"endColumn":15,"startRow":20,"startColumn":14}},{"range":{"endRow":20,"endColumn":34,"startRow":20,"startColumn":15},"structure":[{"value":{"text":"LabeledExprSyntax"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":248,"text":"LabeledExprList","type":"collection","id":252},{"range":{"startColumn":15,"startRow":20,"endRow":20,"endColumn":34},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeLabel"},{"value":{"text":"systemName","kind":"identifier("systemName")"},"name":"label"},{"value":{"text":"nil"},"name":"unexpectedBetweenLabelAndColon"},{"value":{"text":":","kind":"colon"},"name":"colon"},{"value":{"text":"nil"},"name":"unexpectedBetweenColonAndExpression"},{"value":{"text":"StringLiteralExprSyntax"},"ref":"StringLiteralExprSyntax","name":"expression"},{"value":{"text":"nil"},"name":"unexpectedBetweenExpressionAndTrailingComma"},{"value":{"text":"nil"},"name":"trailingComma"},{"value":{"text":"nil"},"name":"unexpectedAfterTrailingComma"}],"parent":252,"text":"LabeledExpr","type":"other","id":253},{"text":"systemName","type":"other","token":{"trailingTrivia":"","leadingTrivia":"","kind":"identifier("systemName")"},"structure":[],"id":254,"range":{"startColumn":15,"endRow":20,"endColumn":25,"startRow":20},"parent":253},{"type":"other","structure":[],"id":255,"parent":253,"token":{"trailingTrivia":"␣<\/span>","leadingTrivia":"","kind":"colon"},"range":{"startColumn":25,"endRow":20,"endColumn":26,"startRow":20},"text":":"},{"range":{"startColumn":27,"endRow":20,"endColumn":34,"startRow":20},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeOpeningPounds"},{"value":{"text":"nil"},"name":"openingPounds"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningPoundsAndOpeningQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"openingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenOpeningQuoteAndSegments"},{"ref":"StringLiteralSegmentListSyntax","value":{"text":"StringLiteralSegmentListSyntax"},"name":"segments"},{"value":{"text":"nil"},"name":"unexpectedBetweenSegmentsAndClosingQuote"},{"value":{"kind":"stringQuote","text":"""},"name":"closingQuote"},{"value":{"text":"nil"},"name":"unexpectedBetweenClosingQuoteAndClosingPounds"},{"value":{"text":"nil"},"name":"closingPounds"},{"value":{"text":"nil"},"name":"unexpectedAfterClosingPounds"}],"parent":253,"text":"StringLiteralExpr","type":"expr","id":256},{"range":{"endRow":20,"endColumn":28,"startRow":20,"startColumn":27},"parent":256,"structure":[],"token":{"kind":"stringQuote","leadingTrivia":"","trailingTrivia":""},"type":"other","id":257,"text":"""},{"range":{"endRow":20,"endColumn":33,"startRow":20,"startColumn":28},"structure":[{"value":{"text":"Element"},"name":"Element"},{"value":{"text":"1"},"name":"Count"}],"parent":256,"text":"StringLiteralSegmentList","type":"collection","id":258},{"range":{"startColumn":28,"startRow":20,"endColumn":33,"endRow":20},"structure":[{"value":{"text":"nil"},"name":"unexpectedBeforeContent"},{"value":{"kind":"stringSegment("trash")","text":"trash"},"name":"content"},{"value":{"text":"nil"},"name":"unexpectedAfterContent"}],"parent":258,"text":"StringSegment","type":"other","id":259},{"structure":[],"type":"other","range":{"endColumn":33,"startColumn":28,"endRow":20,"startRow":20},"token":{"trailingTrivia":"","kind":"stringSegment("trash")","leadingTrivia":""},"parent":259,"text":"trash","id":260},{"parent":256,"type":"other","id":261,"text":""","range":{"endColumn":34,"startColumn":33,"endRow":20,"startRow":20},"structure":[],"token":{"trailingTrivia":"","kind":"stringQuote","leadingTrivia":""}},{"range":{"endColumn":35,"startColumn":34,"endRow":20,"startRow":20},"structure":[],"text":")","type":"other","id":262,"token":{"trailingTrivia":"","kind":"rightParen","leadingTrivia":""},"parent":248},{"range":{"endColumn":35,"startColumn":35,"endRow":20,"startRow":20},"structure":[{"value":{"text":"MultipleTrailingClosureElementSyntax"},"name":"Element"},{"value":{"text":"0"},"name":"Count"}],"parent":248,"text":"MultipleTrailingClosureElementList","type":"collection","id":263},{"parent":244,"token":{"leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":"","kind":"rightBrace"},"range":{"endColumn":8,"startRow":21,"startColumn":7,"endRow":21},"type":"other","id":264,"structure":[],"text":"}"},{"range":{"endColumn":8,"startRow":21,"startColumn":8,"endRow":21},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":184,"text":"MultipleTrailingClosureElementList","type":"collection","id":265},{"id":266,"range":{"startRow":22,"startColumn":5,"endRow":22,"endColumn":6},"type":"other","parent":104,"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"text":"}","structure":[]},{"range":{"startRow":22,"startColumn":6,"endRow":22,"endColumn":6},"structure":[{"name":"Element","value":{"text":"MultipleTrailingClosureElementSyntax"}},{"name":"Count","value":{"text":"0"}}],"parent":100,"text":"MultipleTrailingClosureElementList","type":"collection","id":267},{"parent":96,"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>␣<\/span>␣<\/span>","trailingTrivia":""},"id":268,"range":{"endColumn":4,"startColumn":3,"endRow":23,"startRow":23},"text":"}","type":"other","structure":[]},{"structure":[],"id":269,"type":"other","text":"}","range":{"endColumn":2,"startColumn":1,"endRow":24,"startRow":24},"token":{"kind":"rightBrace","leadingTrivia":"↲<\/span>","trailingTrivia":""},"parent":26},{"text":"","type":"other","parent":0,"token":{"kind":"endOfFile","leadingTrivia":"↲<\/span>","trailingTrivia":""},"range":{"endColumn":1,"startColumn":1,"endRow":25,"startRow":25},"structure":[],"id":270}] diff --git a/Examples/Remaining/swiftui/code.swift b/Examples/Remaining/swiftui/code.swift deleted file mode 100644 index 3a1c97d..0000000 --- a/Examples/Remaining/swiftui/code.swift +++ /dev/null @@ -1,103 +0,0 @@ -import SwiftUI - -// MARK: - Models -struct TodoItem: Identifiable { - let id = UUID() - var title: String - var isCompleted: Bool -} - -// MARK: - View Models -class TodoListViewModel: ObservableObject { - @Published var items: [TodoItem] = [] - @Published var newItemTitle: String = "" - - func addItem() { - guard !newItemTitle.isEmpty else { return } - items.append(TodoItem(title: newItemTitle, isCompleted: false)) - newItemTitle = "" - } - - func toggleItem(_ item: TodoItem) { - if let index = items.firstIndex(where: { $0.id == item.id }) { - items[index].isCompleted.toggle() - } - } - - func deleteItem(_ item: TodoItem) { - items.removeAll { $0.id == item.id } - } -} - -// MARK: - Views -struct TodoListView: View { - @StateObject private var viewModel = TodoListViewModel() - - var body: some View { - NavigationView { - VStack { - // Add new item - HStack { - TextField("New todo item", text: $viewModel.newItemTitle) - .textFieldStyle(RoundedBorderTextFieldStyle()) - - Button(action: viewModel.addItem) { - Image(systemName: "plus.circle.fill") - .foregroundColor(.blue) - } - } - .padding() - - // List of items - List { - ForEach(viewModel.items) { item in - TodoItemRow(item: item) { - viewModel.toggleItem(item) - } - } - .onDelete { indexSet in - indexSet.forEach { index in - viewModel.deleteItem(viewModel.items[index]) - } - } - } - } - .navigationTitle("Todo List") - } - } -} - -struct TodoItemRow: View { - let item: TodoItem - let onToggle: () -> Void - - var body: some View { - HStack { - Button(action: onToggle) { - Image(systemName: item.isCompleted ? "checkmark.circle.fill" : "circle") - .foregroundColor(item.isCompleted ? .green : .gray) - } - - Text(item.title) - .strikethrough(item.isCompleted) - .foregroundColor(item.isCompleted ? .gray : .primary) - } - } -} - -// MARK: - Preview -struct TodoListView_Previews: PreviewProvider { - static var previews: some View { - TodoListView() - } -} - -// MARK: - App Entry Point -@main -struct TodoApp: App { - var body: some Scene { - WindowGroup { - TodoListView() - } - } -} diff --git a/Line.swift b/Line.swift deleted file mode 100644 index 41374c1..0000000 --- a/Line.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// Line.swift -// Lint -// -// Created by Leo Dion on 6/16/25. -// - -/// Represents a single comment line that can be attached to a syntax node when using -/// `.comment { ... }` in the DSL. -public struct Line { - public enum Kind { - /// Regular line comment that starts with `//`. - case line - /// Documentation line comment that starts with `///`. - case doc - } - - public let kind: Kind - public let text: String? - - /// Convenience initializer for a regular line comment without specifying the kind explicitly. - public init(_ text: String) { - self.kind = .line - self.text = text - } - - /// Convenience initialiser. Passing only `kind` will create an empty comment line of that kind. - /// - /// Examples: - /// ```swift - /// Line("MARK: - Models") // defaults to `.line` kind - /// Line(.doc, "Represents a model") // documentation comment - /// Line(.doc) // empty `///` line - /// ``` - public init(_ kind: Kind = .line, _ text: String? = nil) { - self.kind = kind - self.text = text - } -} - -// MARK: - Internal helpers - -extension Line { - /// Convert the `Line` to a SwiftSyntax `TriviaPiece`. - fileprivate var triviaPiece: TriviaPiece { - switch kind { - case .line: - return .lineComment("// " + (text ?? "")) - case .doc: - // Empty doc line should still contain the comment marker so we keep a single `/` if no text. - if let text = text, !text.isEmpty { - return .docLineComment("/// " + text) - } else { - return .docLineComment("///") - } - } - } -} diff --git a/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift index 606f1c4..4b3d653 100644 --- a/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift +++ b/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift @@ -66,7 +66,7 @@ internal struct CommentedCodeBlock: CodeBlock { let newFirstToken = firstToken.with(\.leadingTrivia, commentTrivia + firstToken.leadingTrivia) let rewriter = FirstTokenRewriter(newToken: newFirstToken) - let rewritten = rewriter.visit(Syntax(base.syntax)) + let rewritten = rewriter.rewrite(Syntax(base.syntax)) return rewritten } } diff --git a/Sources/SyntaxKit/ControlFlow/If+Body.swift b/Sources/SyntaxKit/ControlFlow/If+Body.swift index 91d6525..f23554e 100644 --- a/Sources/SyntaxKit/ControlFlow/If+Body.swift +++ b/Sources/SyntaxKit/ControlFlow/If+Body.swift @@ -30,8 +30,9 @@ import SwiftSyntax extension If { - /// Builds the body block for the if statement. - internal func buildBody() -> CodeBlockSyntax { + /// Builds the body of the if expression. + /// - Returns: The code block syntax for the body. + public func buildBody() -> CodeBlockSyntax { CodeBlockSyntax( leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), statements: buildBodyStatements(from: body), @@ -39,8 +40,10 @@ extension If { ) } - /// Builds the statements for a code block from an array of CodeBlocks. - internal func buildBodyStatements(from blocks: [CodeBlock]) -> CodeBlockItemListSyntax { + /// Builds the body statements from an array of code blocks. + /// - Parameter blocks: The code blocks to convert to statements. + /// - Returns: The code block item list syntax. + public func buildBodyStatements(from blocks: [CodeBlock]) -> CodeBlockItemListSyntax { CodeBlockItemListSyntax( blocks.compactMap { block in createCodeBlockItem(from: block)?.with(\.trailingTrivia, .newline) diff --git a/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift b/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift index c7c41af..f26f1ae 100644 --- a/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift +++ b/Sources/SyntaxKit/ControlFlow/If+CodeBlockItem.swift @@ -31,7 +31,9 @@ import SwiftSyntax extension If { /// Creates a code block item from a CodeBlock. - internal func createCodeBlockItem(from block: CodeBlock) -> CodeBlockItemSyntax? { + /// - Parameter block: The code block to convert. + /// - Returns: The code block item syntax or nil if conversion is not possible. + public func createCodeBlockItem(from block: CodeBlock) -> CodeBlockItemSyntax? { if let enumCase = block as? EnumCase { // Handle EnumCase specially - use expression syntax for enum cases in expressions return CodeBlockItemSyntax(item: .expr(enumCase.exprSyntax)) diff --git a/Sources/SyntaxKit/ControlFlow/If+Conditions.swift b/Sources/SyntaxKit/ControlFlow/If+Conditions.swift index 61b7725..87ecb3f 100644 --- a/Sources/SyntaxKit/ControlFlow/If+Conditions.swift +++ b/Sources/SyntaxKit/ControlFlow/If+Conditions.swift @@ -30,8 +30,9 @@ import SwiftSyntax extension If { - /// Builds the condition elements for the if statement. - internal func buildConditions() -> ConditionElementListSyntax { + /// Builds the conditions for the if expression. + /// - Returns: The condition element list syntax. + public func buildConditions() -> ConditionElementListSyntax { ConditionElementListSyntax( conditions.enumerated().map { index, block in let needsComma = index < conditions.count - 1 diff --git a/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift b/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift index 926b490..7abd91c 100644 --- a/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift +++ b/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift @@ -30,8 +30,9 @@ import SwiftSyntax extension If { - /// Builds the else body for the if statement, handling else-if chains. - internal func buildElseBody() -> IfExprSyntax.ElseBody? { + /// Builds the else body for the if expression. + /// - Returns: The else body syntax or nil if no else body exists. + public func buildElseBody() -> IfExprSyntax.ElseBody? { guard let elseBlocks = elseBody else { return nil } diff --git a/Sources/SyntaxKit/Core/CodeBlock.swift b/Sources/SyntaxKit/Core/CodeBlock.swift index e6d5588..e29c41d 100644 --- a/Sources/SyntaxKit/Core/CodeBlock.swift +++ b/Sources/SyntaxKit/Core/CodeBlock.swift @@ -34,4 +34,25 @@ import SwiftSyntax public protocol CodeBlock { /// The SwiftSyntax representation of the code block. var syntax: SyntaxProtocol { get } + + /// Calls a method on this code block with the given name and parameters. + /// - Parameters: + /// - name: The name of the method to call. + /// - parameters: A closure that returns the parameters for the method call. + /// - Returns: A code block representing the method call. + func call(_ name: String, @ParameterExpBuilderResult _ parameters: () -> [ParameterExp]) + -> CodeBlock +} + +extension CodeBlock { + /// Calls a method on this code block with the given name and parameters. + /// - Parameters: + /// - name: The name of the method to call. + /// - parameters: A closure that returns the parameters for the method call. + /// - Returns: A code block representing the method call. + public func call( + _ name: String, @ParameterExpBuilderResult _ parameters: () -> [ParameterExp] = { [] } + ) -> CodeBlock { + FunctionCallExp(base: self, methodName: name, parameters: parameters()) + } } diff --git a/Sources/SyntaxKit/Core/TypeRepresentable.swift b/Sources/SyntaxKit/Core/TypeRepresentable.swift new file mode 100644 index 0000000..13c059a --- /dev/null +++ b/Sources/SyntaxKit/Core/TypeRepresentable.swift @@ -0,0 +1,41 @@ +// +// TypeRepresentable.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A protocol that represents a type that can be converted to SwiftSyntax. +public protocol TypeRepresentable { + /// Returns the SwiftSyntax representation of the conforming type. + var typeSyntax: TypeSyntax { get } +} + +extension String: TypeRepresentable { + /// Returns the SwiftSyntax representation of the conforming type. + public var typeSyntax: TypeSyntax { TypeSyntax(IdentifierTypeSyntax(name: .identifier(self))) } +} diff --git a/Sources/SyntaxKit/Declarations/Import.swift b/Sources/SyntaxKit/Declarations/Import.swift new file mode 100644 index 0000000..191a037 --- /dev/null +++ b/Sources/SyntaxKit/Declarations/Import.swift @@ -0,0 +1,144 @@ +// +// Import.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift `import` declaration. +public struct Import: CodeBlock { + private let moduleName: String + private var accessModifier: String? + private var attributes: [AttributeInfo] = [] + + /// Creates an `import` declaration. + /// - Parameter moduleName: The name of the module to import. + public init(_ moduleName: String) { + self.moduleName = moduleName + } + + /// Sets the access modifier for the import declaration. + /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Returns: A copy of the import with the access modifier set. + public func access(_ access: String) -> Self { + var copy = self + copy.accessModifier = access + return copy + } + + /// Adds an attribute to the import declaration. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the import with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + + public var syntax: SyntaxProtocol { + // Build access modifier + var modifiers: DeclModifierListSyntax = [] + if let access = accessModifier { + let keyword: Keyword + switch access { + case "public": + keyword = .public + case "private": + keyword = .private + case "internal": + keyword = .internal + case "fileprivate": + keyword = .fileprivate + default: + keyword = .public // fallback + } + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + ]) + } + + // Build import path + let importPath = ImportPathComponentListSyntax([ + ImportPathComponentSyntax(name: .identifier(moduleName)) + ]) + + return ImportDeclSyntax( + attributes: buildAttributeList(from: attributes), + modifiers: modifiers, + importKeyword: .keyword(.import, trailingTrivia: .space), + importKindSpecifier: nil, + path: importPath + ) + } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.map { attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ) + ) + } + return AttributeListSyntax(attributeElements) + } +} diff --git a/Sources/SyntaxKit/Declarations/Init.swift b/Sources/SyntaxKit/Declarations/Init.swift index 5ef1c2c..b9b760d 100644 --- a/Sources/SyntaxKit/Declarations/Init.swift +++ b/Sources/SyntaxKit/Declarations/Init.swift @@ -51,12 +51,42 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { } public var exprSyntax: ExprSyntax { - let args = LabeledExprListSyntax( - parameters.enumerated().compactMap { index, param in - guard let element = param.syntax as? LabeledExprSyntax else { + var args = parameters + var trailingClosure: ClosureExprSyntax? + + // If the last parameter is an unlabeled closure, use it as a trailing closure + if let last = args.last, last.isUnlabeledClosure { + // Flatten nested unlabeled closures + if let closure = last.value as? Closure, + closure.body.count == 1, + let innerParam = closure.body.first as? ParameterExp, + innerParam.isUnlabeledClosure, + let innerClosure = innerParam.value as? Closure + { + trailingClosure = innerClosure.syntax.as(ClosureExprSyntax.self) + } else if let closure = last.value as? Closure { + trailingClosure = closure.syntax.as(ClosureExprSyntax.self) + } else { + trailingClosure = last.syntax.as(ClosureExprSyntax.self) + } + args.removeLast() + } + + let labeledArgs = LabeledExprListSyntax( + args.enumerated().compactMap { index, param in + let element: LabeledExprSyntax + if let labeled = param.syntax as? LabeledExprSyntax { + element = labeled + } else if let unlabeled = param.syntax.as(ExprSyntax.self) { + element = LabeledExprSyntax( + label: nil, + colon: nil, + expression: unlabeled + ) + } else { return nil } - if index < parameters.count - 1 { + if index < args.count - 1 { return element.with( \.trailingComma, .commaToken(trailingTrivia: .space) @@ -65,14 +95,17 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { return element } ) + + let requiresParanthesis = !labeledArgs.isEmpty || trailingClosure == nil return ExprSyntax( FunctionCallExprSyntax( calledExpression: ExprSyntax( DeclReferenceExprSyntax(baseName: .identifier(type)) ), - leftParen: .leftParenToken(), - arguments: args, - rightParen: .rightParenToken() + leftParen: requiresParanthesis ? .leftParenToken() : nil, + arguments: labeledArgs, + rightParen: requiresParanthesis ? .rightParenToken() : nil, + trailingClosure: trailingClosure ) ) } @@ -81,6 +114,24 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { exprSyntax } + /// Calls a method on the initialized object. + /// - Parameter methodName: The name of the method to call. + /// - Returns: A ``FunctionCallExp`` that represents the method call. + public func call(_ methodName: String) -> CodeBlock { + FunctionCallExp(base: self, methodName: methodName) + } + + /// Calls a method on the initialized object with parameters. + /// - Parameters: + /// - methodName: The name of the method to call. + /// - params: A ``ParameterExpBuilder`` that provides the parameters for the method call. + /// - Returns: A ``FunctionCallExp`` that represents the method call. + public func call(_ methodName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) + -> CodeBlock + { + FunctionCallExp(base: self, methodName: methodName, parameters: params()) + } + // MARK: - LiteralValue Conformance public var typeName: String { diff --git a/Sources/SyntaxKit/Declarations/Struct.swift b/Sources/SyntaxKit/Declarations/Struct.swift index e4dc406..4b2dc56 100644 --- a/Sources/SyntaxKit/Declarations/Struct.swift +++ b/Sources/SyntaxKit/Declarations/Struct.swift @@ -36,6 +36,7 @@ public struct Struct: CodeBlock { private var genericParameter: String? private var inheritance: [String] = [] private var attributes: [AttributeInfo] = [] + private var accessModifier: String? /// Creates a `struct` declaration. /// - Parameters: @@ -64,6 +65,15 @@ public struct Struct: CodeBlock { return copy } + /// Sets the access modifier for the struct declaration. + /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Returns: A copy of the struct with the access modifier set. + public func access(_ access: String) -> Self { + var copy = self + copy.accessModifier = access + return copy + } + /// Adds an attribute to the struct declaration. /// - Parameters: /// - attribute: The attribute name (without the @ symbol). @@ -129,8 +139,30 @@ public struct Struct: CodeBlock { rightBrace: .rightBraceToken(leadingTrivia: .newline) ) + // Build access modifier + var modifiers: DeclModifierListSyntax = [] + if let access = accessModifier { + let keyword: Keyword + switch access { + case "public": + keyword = .public + case "private": + keyword = .private + case "internal": + keyword = .internal + case "fileprivate": + keyword = .fileprivate + default: + keyword = .public // fallback + } + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + ]) + } + return StructDeclSyntax( attributes: buildAttributeList(from: attributes), + modifiers: modifiers, structKeyword: structKeyword, name: identifier, genericParameterClause: genericParameterClause, diff --git a/Sources/SyntaxKit/Expressions/Closure+Body.swift b/Sources/SyntaxKit/Expressions/Closure+Body.swift new file mode 100644 index 0000000..c93a021 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/Closure+Body.swift @@ -0,0 +1,77 @@ +// +// Closure+Body.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Closure { + /// Builds the body block for the closure. + internal func buildBodyBlock() -> CodeBlockItemListSyntax { + CodeBlockItemListSyntax( + body.compactMap(buildBodyItem) + ) + } + + /// Builds a body item from a code block. + private func buildBodyItem(from codeBlock: CodeBlock) -> CodeBlockItemSyntax? { + if let decl = codeBlock.syntax.as(DeclSyntax.self) { + return CodeBlockItemSyntax(item: .decl(decl)).with(\.trailingTrivia, .newline) + } else if let paramExp = codeBlock as? ParameterExp { + return buildParameterExpressionItem(paramExp) + } else if let exprBlock = codeBlock as? ExprCodeBlock { + return CodeBlockItemSyntax(item: .expr(exprBlock.exprSyntax)).with( + \.trailingTrivia, .newline + ) + } else if let expr = codeBlock.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)).with( + \.trailingTrivia, .newline + ) + } else if let stmt = codeBlock.syntax.as(StmtSyntax.self) { + return CodeBlockItemSyntax(item: .stmt(stmt)).with(\.trailingTrivia, .newline) + } + return nil + } + + /// Builds a parameter expression item. + private func buildParameterExpressionItem(_ paramExp: ParameterExp) -> CodeBlockItemSyntax? { + if let exprBlock = paramExp.value as? ExprCodeBlock { + return CodeBlockItemSyntax(item: .expr(exprBlock.exprSyntax)).with( + \.trailingTrivia, .newline + ) + } else if let expr = paramExp.value.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(expr)).with( + \.trailingTrivia, .newline + ) + } else if let paramExpr = paramExp.syntax.as(ExprSyntax.self) { + return CodeBlockItemSyntax(item: .expr(paramExpr)).with( + \.trailingTrivia, .newline + ) + } + return nil + } +} diff --git a/Sources/SyntaxKit/Expressions/Closure+Capture.swift b/Sources/SyntaxKit/Expressions/Closure+Capture.swift new file mode 100644 index 0000000..87fd215 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/Closure+Capture.swift @@ -0,0 +1,105 @@ +// +// Closure+Capture.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Represents capture specifier and name information for closure captures. +private struct CaptureInfo { + let specifier: ClosureCaptureSpecifierSyntax? + let name: TokenSyntax + + init(from param: ParameterExp) { + if let refExp = param.value as? ReferenceExp { + self.init(fromReference: refExp) + } else { + self.init(fromParameter: param) + } + } + + private init(fromReference refExp: ReferenceExp) { + let keyword: Keyword + switch refExp.captureReferenceType.lowercased() { + case "weak": + keyword = .weak + case "unowned": + keyword = .unowned + default: + keyword = .weak // fallback to weak + } + + self.specifier = ClosureCaptureSpecifierSyntax( + specifier: .keyword(keyword, trailingTrivia: .space) + ) + + if let varExp = refExp.captureExpression as? VariableExp { + self.name = .identifier(varExp.name) + } else { + self.name = .identifier("self") // fallback + } + } + + private init(fromParameter param: ParameterExp) { + self.specifier = nil + + if let varExp = param.value as? VariableExp { + self.name = .identifier(varExp.name) + } else { + self.name = .identifier("self") // fallback + } + } +} + +extension Closure { + /// Builds the capture clause for the closure. + internal func buildCaptureClause() -> ClosureCaptureClauseSyntax? { + guard !capture.isEmpty else { + return nil + } + + return ClosureCaptureClauseSyntax( + leftSquare: .leftSquareToken(), + items: ClosureCaptureListSyntax( + capture.map(buildCaptureItem) + ), + rightSquare: .rightSquareToken() + ) + } + + /// Builds a capture item from a parameter expression. + private func buildCaptureItem(from param: ParameterExp) -> ClosureCaptureSyntax { + let captureInfo = CaptureInfo(from: param) + + return ClosureCaptureSyntax( + specifier: captureInfo.specifier, + name: captureInfo.name, + initializer: nil, + trailingComma: nil + ) + } +} diff --git a/Sources/SyntaxKit/Expressions/Closure+Signature.swift b/Sources/SyntaxKit/Expressions/Closure+Signature.swift new file mode 100644 index 0000000..1da5a37 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/Closure+Signature.swift @@ -0,0 +1,113 @@ +// +// Closure+Signature.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Closure { + /// Builds the signature for the closure. + internal func buildSignature(captureClause: ClosureCaptureClauseSyntax?) + -> ClosureSignatureSyntax? + { + guard needsSignature else { + return nil + } + + return ClosureSignatureSyntax( + attributes: buildAttributeList(), + capture: captureClause, + parameterClause: buildParameterClause().map { .parameterClause($0) }, + effectSpecifiers: nil, + returnClause: buildReturnClause(), + inKeyword: .keyword(.in, leadingTrivia: .space, trailingTrivia: .space) + ) + } + + /// Builds the attribute list for the closure signature. + private func buildAttributeList() -> AttributeListSyntax { + guard !attributes.isEmpty else { + return AttributeListSyntax([]) + } + + return AttributeListSyntax( + attributes.enumerated().map { idx, attr in + AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax( + name: .identifier(attr.name), + trailingTrivia: (capture.isEmpty || idx != attributes.count - 1) + ? Trivia() : .space + ), + leftParen: nil, + arguments: nil, + rightParen: nil + ) + ) + } + ) + } + + /// Builds the parameter clause for the closure signature. + private func buildParameterClause() -> ClosureParameterClauseSyntax? { + guard !parameters.isEmpty else { + return nil + } + + return ClosureParameterClauseSyntax( + leftParen: .leftParenToken(), + parameters: ClosureParameterListSyntax( + parameters.map(buildParameterSyntax) + ), + rightParen: .rightParenToken() + ) + } + + /// Builds parameter syntax from a closure parameter. + private func buildParameterSyntax(from param: ClosureParameter) -> ClosureParameterSyntax { + ClosureParameterSyntax( + attributes: AttributeListSyntax([]), + firstName: .identifier(param.name), + secondName: nil, + colon: param.name.isEmpty ? nil : .colonToken(trailingTrivia: .space), + type: param.type?.typeSyntax as? TypeSyntax, + ellipsis: nil, + trailingComma: nil + ) + } + + /// Builds the return clause for the closure signature. + private func buildReturnClause() -> ReturnClauseSyntax? { + returnType.map { + ReturnClauseSyntax( + arrow: .arrowToken(trailingTrivia: .space), + type: $0.typeSyntax + ) + } + } +} diff --git a/Sources/SyntaxKit/Expressions/Closure.swift b/Sources/SyntaxKit/Expressions/Closure.swift new file mode 100644 index 0000000..59be944 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/Closure.swift @@ -0,0 +1,76 @@ +// +// Closure.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Represents a closure expression in Swift code. +public struct Closure: CodeBlock { + public let capture: [ParameterExp] + public let parameters: [ClosureParameter] + public let returnType: String? + public let body: [CodeBlock] + internal var attributes: [AttributeInfo] = [] + + internal var needsSignature: Bool { + !parameters.isEmpty || returnType != nil || !capture.isEmpty || !attributes.isEmpty + } + + public init( + @ParameterExpBuilderResult capture: () -> [ParameterExp] = { [] }, + @ClosureParameterBuilderResult parameters: () -> [ClosureParameter] = { [] }, + returns returnType: String? = nil, + @CodeBlockBuilderResult body: () -> [CodeBlock] + ) { + self.capture = capture() + self.parameters = parameters() + self.returnType = returnType + self.body = body() + } + + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + + public var syntax: SyntaxProtocol { + let captureClause = buildCaptureClause() + let signature = buildSignature(captureClause: captureClause) + let bodyBlock = buildBodyBlock() + + return ExprSyntax( + ClosureExprSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + signature: signature, + statements: bodyBlock, + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + ) + } +} diff --git a/Sources/SyntaxKit/Expressions/ClosureParameter.swift b/Sources/SyntaxKit/Expressions/ClosureParameter.swift new file mode 100644 index 0000000..ef73718 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/ClosureParameter.swift @@ -0,0 +1,57 @@ +// +// ClosureParameter.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Represents a parameter in a closure signature. +public struct ClosureParameter: TypeRepresentable { + public var name: String + public var type: String? + internal var attributes: [AttributeInfo] + + public init(_ name: String, type: String? = nil) { + self.name = name + self.type = type + self.attributes = [] + } + + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + + public var typeSyntax: TypeSyntax { + if let type = type { + return TypeSyntax(IdentifierTypeSyntax(name: .identifier(type))) + } else { + return TypeSyntax(IdentifierTypeSyntax(name: .identifier("Any"))) + } + } +} diff --git a/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift b/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift new file mode 100644 index 0000000..8cb24c5 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift @@ -0,0 +1,67 @@ +// +// ClosureParameterBuilderResult.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// A result builder for creating closure parameter lists. +@resultBuilder +public enum ClosureParameterBuilderResult { + /// Builds a block of closure parameters. + /// - Parameter components: The closure parameters to combine. + /// - Returns: An array of closure parameters. + public static func buildBlock(_ components: ClosureParameter...) -> [ClosureParameter] { + components + } + + /// Builds an optional closure parameter. + /// - Parameter component: The optional closure parameter. + /// - Returns: An array containing the parameter if present, otherwise empty. + public static func buildOptional(_ component: ClosureParameter?) -> [ClosureParameter] { + component.map { [$0] } ?? [] + } + + /// Builds the first branch of an either expression. + /// - Parameter component: The closure parameter from the first branch. + /// - Returns: An array containing the parameter. + public static func buildEither(first component: ClosureParameter) -> [ClosureParameter] { + [component] + } + + /// Builds the second branch of an either expression. + /// - Parameter component: The closure parameter from the second branch. + /// - Returns: An array containing the parameter. + public static func buildEither(second component: ClosureParameter) -> [ClosureParameter] { + [component] + } + + /// Builds an array of closure parameters. + /// - Parameter components: The arrays of closure parameters to flatten. + /// - Returns: A flattened array of closure parameters. + public static func buildArray(_ components: [ClosureParameter]) -> [ClosureParameter] { + components + } +} diff --git a/Sources/SyntaxKit/Expressions/ClosureType.swift b/Sources/SyntaxKit/Expressions/ClosureType.swift new file mode 100644 index 0000000..d20dbcc --- /dev/null +++ b/Sources/SyntaxKit/Expressions/ClosureType.swift @@ -0,0 +1,221 @@ +// +// ClosureType.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift closure type (e.g., `(Date) -> Void`). +public struct ClosureType: CodeBlock, TypeRepresentable { + private let parameters: [ClosureParameter] + private let returnType: String? + private var attributes: [AttributeInfo] = [] + + /// Creates a closure type with no parameters. + /// - Parameter returns: The return type of the closure. + public init(returns returnType: String? = nil) { + self.parameters = [] + self.returnType = returnType + } + + /// Creates a closure type with parameters. + /// - Parameters: + /// - returns: The return type of the closure. + /// - parameters: A ``ClosureParameterBuilderResult`` that provides the parameters. + internal init( + returns returnType: String? = nil, + @ClosureParameterBuilderResult _ parameters: () -> [ClosureParameter] + ) { + self.parameters = parameters() + self.returnType = returnType + } + + /// Adds an attribute to the closure type. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the closure type with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + + public var syntax: SyntaxProtocol { + // Build parameters + let paramList = parameters.map { param in + TupleTypeElementSyntax( + type: param.type.map { IdentifierTypeSyntax(name: .identifier($0)) } + ?? IdentifierTypeSyntax(name: .identifier("Any")) + ) + } + + // Build return clause + var returnClause: ReturnClauseSyntax? + if let returnType = returnType { + returnClause = ReturnClauseSyntax( + arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(returnType)) + ) + } + + // Build function type + let functionType = FunctionTypeSyntax( + leftParen: .leftParenToken(), + parameters: TupleTypeElementListSyntax(paramList), + rightParen: .rightParenToken(), + effectSpecifiers: nil, + returnClause: returnClause + ?? ReturnClauseSyntax( + arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier("Void")) + ) + ) + + // Build attributed type if there are attributes + if !attributes.isEmpty { + return AttributedTypeSyntax( + specifiers: TypeSpecifierListSyntax([]), + attributes: buildAttributeList(from: attributes), + baseType: functionType + ) + } else { + return functionType + } + } + + private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + if attributes.isEmpty { + return AttributeListSyntax([]) + } + let attributeElements = attributes.enumerated().map { index, attributeInfo in + let arguments = attributeInfo.arguments + + var leftParen: TokenSyntax? + var rightParen: TokenSyntax? + var argumentsSyntax: AttributeSyntax.Arguments? + + if !arguments.isEmpty { + leftParen = .leftParenToken() + rightParen = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + argumentsSyntax = .argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + } + + // Add leading space for all but the first attribute + let atSign = + index == 0 ? TokenSyntax.atSignToken() : TokenSyntax.atSignToken(leadingTrivia: .space) + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: atSign, + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: leftParen, + arguments: argumentsSyntax, + rightParen: rightParen + ).with(\.trailingTrivia, index == attributes.count - 1 ? .space : Trivia()) + ) + } + return AttributeListSyntax(attributeElements) + } + + /// A string representation of the closure type. + public var description: String { + let params = parameters.map { param in + if let type = param.type { + return "\(param.name): \(type)" + } else { + return param.name + } + } + .joined(separator: ", ") + let attr = attributes.map { "@\($0.name)" }.joined(separator: " ") + let paramList = "(\(params))" + let ret = returnType ?? "Void" + let typeString = "\(paramList) -> \(ret)" + return attr.isEmpty ? typeString : "\(attr) \(typeString)" + } + + /// The SwiftSyntax representation of this closure type. + public var typeSyntax: TypeSyntax { + // Build parameters + let paramList = parameters.map { param in + TupleTypeElementSyntax( + type: param.type.map { IdentifierTypeSyntax(name: .identifier($0)) } + ?? IdentifierTypeSyntax(name: .identifier(param.name)) + ) + } + // Build return clause + var returnClause: ReturnClauseSyntax? + if let returnType = returnType { + returnClause = ReturnClauseSyntax( + arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier(returnType)) + ) + } + + // Build function type + let functionType = FunctionTypeSyntax( + leftParen: .leftParenToken(), + parameters: TupleTypeElementListSyntax(paramList), + rightParen: .rightParenToken(), + effectSpecifiers: nil, + returnClause: returnClause + ?? ReturnClauseSyntax( + arrow: .arrowToken(leadingTrivia: .space, trailingTrivia: .space), + type: IdentifierTypeSyntax(name: .identifier("Void")) + ) + ) + + // Apply attributes if any + if !attributes.isEmpty { + return TypeSyntax( + AttributedTypeSyntax( + specifiers: TypeSpecifierListSyntax([]), + attributes: buildAttributeList(from: attributes), + baseType: TypeSyntax(functionType) + ) + ) + } else { + return TypeSyntax(functionType) + } + } +} diff --git a/Sources/SyntaxKit/Expressions/ConditionalOp.swift b/Sources/SyntaxKit/Expressions/ConditionalOp.swift new file mode 100644 index 0000000..6e3d416 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/ConditionalOp.swift @@ -0,0 +1,88 @@ +// +// ConditionalOp.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift ternary conditional operator expression (`condition ? then : else`). +public struct ConditionalOp: CodeBlock { + private let condition: CodeBlock + private let thenExpression: CodeBlock + private let elseExpression: CodeBlock + + /// Creates a ternary conditional operator expression. + /// - Parameters: + /// - if: The condition expression. + /// - then: The expression to evaluate if the condition is true. + /// - else: The expression to evaluate if the condition is false. + public init( + if condition: CodeBlock, + then thenExpression: CodeBlock, + else elseExpression: CodeBlock + ) { + self.condition = condition + self.thenExpression = thenExpression + self.elseExpression = elseExpression + } + + public var syntax: SyntaxProtocol { + let conditionExpr = ExprSyntax( + fromProtocol: condition.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + + // Handle EnumCase specially - use asExpressionSyntax for expressions + let thenExpr: ExprSyntax + if let enumCase = thenExpression as? EnumCase { + thenExpr = enumCase.asExpressionSyntax + } else { + thenExpr = ExprSyntax( + fromProtocol: thenExpression.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + } + + let elseExpr: ExprSyntax + if let enumCase = elseExpression as? EnumCase { + elseExpr = enumCase.asExpressionSyntax + } else { + elseExpr = ExprSyntax( + fromProtocol: elseExpression.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + } + + return TernaryExprSyntax( + condition: conditionExpr, + questionMark: .infixQuestionMarkToken(leadingTrivia: .space, trailingTrivia: .space), + thenExpression: thenExpr, + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + elseExpression: elseExpr + ) + } +} diff --git a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift index e30e5d5..c720e7f 100644 --- a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift +++ b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift @@ -34,37 +34,71 @@ public struct FunctionCallExp: CodeBlock { internal let baseName: String internal let methodName: String internal let parameters: [ParameterExp] + private let base: CodeBlock? - /// Creates a function call expression. - /// - Parameters: - /// - baseName: The name of the base variable. - /// - methodName: The name of the method to call. + /// Creates a function call expression on a variable name. public init(baseName: String, methodName: String) { self.baseName = baseName self.methodName = methodName self.parameters = [] + self.base = nil } - /// Creates a function call expression with parameters. - /// - Parameters: - /// - baseName: The name of the base variable. - /// - methodName: The name of the method to call. - /// - parameters: The parameters for the method call. + /// Creates a function call expression with parameters on a variable name. public init(baseName: String, methodName: String, parameters: [ParameterExp]) { self.baseName = baseName self.methodName = methodName self.parameters = parameters + self.base = nil + } + + /// Creates a function call expression on an arbitrary base expression. + public init(base: CodeBlock, methodName: String, parameters: [ParameterExp] = []) { + self.baseName = "" + self.methodName = methodName + self.parameters = parameters + self.base = base } public var syntax: SyntaxProtocol { - let base = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(baseName))) - let method = TokenSyntax.identifier(methodName) - let args = LabeledExprListSyntax( - parameters.enumerated().map { index, param in + let baseExpr: ExprSyntax + if let base = base { + if let exprSyntax = base.syntax.as(ExprSyntax.self) { + // If the base is a ConditionalOp, wrap it in parentheses for proper precedence + if base is ConditionalOp { + baseExpr = ExprSyntax( + TupleExprSyntax( + leftParen: .leftParenToken(), + elements: LabeledExprListSyntax([ + LabeledExprSyntax(expression: exprSyntax) + ]), + rightParen: .rightParenToken() + ) + ) + } else { + baseExpr = exprSyntax + } + } else { + baseExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } + } else { + baseExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(baseName))) + } + + // Trailing closure logic + var args = parameters + var trailingClosure: ClosureExprSyntax? + if let last = args.last, last.isUnlabeledClosure { + trailingClosure = last.syntax.as(ClosureExprSyntax.self) + args.removeLast() + } + + let labeledArgs = LabeledExprListSyntax( + args.enumerated().map { index, param in let expr = param.syntax if let labeled = expr as? LabeledExprSyntax { var element = labeled - if index < parameters.count - 1 { + if index < args.count - 1 { element = element.with( \.trailingComma, .commaToken(trailingTrivia: .space) @@ -72,11 +106,11 @@ public struct FunctionCallExp: CodeBlock { } return element } else if let unlabeled = expr as? ExprSyntax { - return TupleExprElementSyntax( + return LabeledExprSyntax( label: nil, colon: nil, expression: unlabeled, - trailingComma: index < parameters.count - 1 + trailingComma: index < args.count - 1 ? .commaToken(trailingTrivia: .space) : nil ) @@ -85,19 +119,21 @@ public struct FunctionCallExp: CodeBlock { } } ) - return ExprSyntax( - FunctionCallExprSyntax( - calledExpression: ExprSyntax( - MemberAccessExprSyntax( - base: base, - dot: .periodToken(), - name: method - ) - ), - leftParen: .leftParenToken(), - arguments: args, - rightParen: .rightParenToken() - ) + + var functionCall = FunctionCallExprSyntax( + calledExpression: ExprSyntax( + MemberAccessExprSyntax( + base: baseExpr, + dot: .periodToken(), + name: .identifier(methodName) + ) + ), + leftParen: .leftParenToken(), + arguments: labeledArgs, + rightParen: .rightParenToken(), + trailingClosure: trailingClosure ) + + return ExprSyntax(functionCall) } } diff --git a/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift b/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift new file mode 100644 index 0000000..433ebc4 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift @@ -0,0 +1,58 @@ +// +// OptionalChainingExp.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift optional chaining expression (e.g., `self?`). +public struct OptionalChainingExp: CodeBlock { + private let base: CodeBlock + + /// Creates an optional chaining expression. + /// - Parameter base: The base expression to make optional. + public init(base: CodeBlock) { + self.base = base + } + + public var syntax: SyntaxProtocol { + // Convert base.syntax to ExprSyntax more safely + let baseExpr: ExprSyntax + if let exprSyntax = base.syntax.as(ExprSyntax.self) { + baseExpr = exprSyntax + } else { + // Fallback to a default expression if conversion fails + baseExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } + + // Add optional chaining operator + return PostfixOperatorExprSyntax( + expression: baseExpr, + operator: .postfixOperator("?", trailingTrivia: []) + ) + } +} diff --git a/Sources/SyntaxKit/Expressions/ReferenceExp.swift b/Sources/SyntaxKit/Expressions/ReferenceExp.swift new file mode 100644 index 0000000..19b1c6b --- /dev/null +++ b/Sources/SyntaxKit/Expressions/ReferenceExp.swift @@ -0,0 +1,74 @@ +// +// ReferenceExp.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift reference expression (e.g., `weak self`, `unowned self`). +public struct ReferenceExp: CodeBlock { + private let base: CodeBlock + private let referenceType: String + + /// Creates a reference expression. + /// - Parameters: + /// - base: The base expression to reference. + /// - referenceType: The type of reference (e.g., "weak", "unowned"). + public init(base: CodeBlock, referenceType: String) { + self.base = base + self.referenceType = referenceType + } + + public var syntax: SyntaxProtocol { + // For capture lists, we need to create a proper reference + // This will be handled by the Closure syntax when used in capture lists + let baseExpr: ExprSyntax + if let enumCase = base as? EnumCase { + // Handle EnumCase specially - use expression syntax for enum cases in expressions + baseExpr = enumCase.asExpressionSyntax + } else { + baseExpr = ExprSyntax( + fromProtocol: base.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + } + + // Create a custom expression that represents a reference + // This will be used by the Closure to create proper capture syntax + return baseExpr + } + + /// Returns the base expression for use in capture lists + internal var captureExpression: CodeBlock { + base + } + + /// Returns the reference type for use in capture lists + internal var captureReferenceType: String { + referenceType + } +} diff --git a/Sources/SyntaxKit/Expressions/Task.swift b/Sources/SyntaxKit/Expressions/Task.swift new file mode 100644 index 0000000..56b1b32 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/Task.swift @@ -0,0 +1,102 @@ +// +// Task.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A Swift Task expression for structured concurrency. +public struct Task: CodeBlock { + private let body: [CodeBlock] + private var attributes: [AttributeInfo] = [] + + /// Creates a Task expression. + /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the task. + public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + self.body = content() + } + + /// Adds an attribute to the task. + /// - Parameters: + /// - attribute: The attribute name (without the @ symbol). + /// - arguments: The arguments for the attribute, if any. + /// - Returns: A copy of the task with the attribute added. + public func attribute(_ attribute: String, arguments: [String] = []) -> Self { + var copy = self + copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) + return copy + } + + public var syntax: SyntaxProtocol { + let bodyBlock = CodeBlockSyntax( + leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), + statements: CodeBlockItemListSyntax( + body.compactMap { block in + var item: CodeBlockItemSyntax? + if let decl = block.syntax.as(DeclSyntax.self) { + item = CodeBlockItemSyntax(item: .decl(decl)) + } else if let expr = block.syntax.as(ExprSyntax.self) { + item = CodeBlockItemSyntax(item: .expr(expr)) + } else if let stmt = block.syntax.as(StmtSyntax.self) { + item = CodeBlockItemSyntax(item: .stmt(stmt)) + } + return item?.with(\.trailingTrivia, .newline) + } + ), + rightBrace: .rightBraceToken(leadingTrivia: .newline) + ) + + let taskExpr = FunctionCallExprSyntax( + calledExpression: ExprSyntax( + DeclReferenceExprSyntax(baseName: .identifier("Task")) + ), + leftParen: .leftParenToken(), + arguments: LabeledExprListSyntax([ + LabeledExprSyntax( + label: nil, + colon: nil, + expression: ExprSyntax( + ClosureExprSyntax( + signature: nil, + statements: bodyBlock.statements + ) + ) + ) + ]), + rightParen: .rightParenToken() + ) + + // Add attributes if present + if !attributes.isEmpty { + // For now, just return the task expression without attributes + // since AttributedExprSyntax is not available + return ExprSyntax(taskExpr) + } else { + return ExprSyntax(taskExpr) + } + } +} diff --git a/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift b/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift index 3289a17..306f912 100644 --- a/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift +++ b/Sources/SyntaxKit/Functions/FunctionParameterSyntax+Init.swift @@ -88,7 +88,7 @@ extension FunctionParameterSyntax { firstName: parameterNames.firstNameToken, secondName: parameterNames.secondNameToken, colon: .colonToken(trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(parameter.type)), + type: parameter.type.typeSyntax, defaultValue: parameter.defaultValue.map { InitializerClauseSyntax( equal: .equalToken( @@ -105,7 +105,7 @@ extension FunctionParameterSyntax { if !isLast { paramSyntax = paramSyntax.with( \.trailingComma, - .commaToken(trailingTrivia: .space) + TokenSyntax.commaToken(trailingTrivia: .space) ) } diff --git a/Sources/SyntaxKit/Functions/FunctionRequirement.swift b/Sources/SyntaxKit/Functions/FunctionRequirement.swift index 6609a9c..07cec1d 100644 --- a/Sources/SyntaxKit/Functions/FunctionRequirement.swift +++ b/Sources/SyntaxKit/Functions/FunctionRequirement.swift @@ -87,7 +87,7 @@ public struct FunctionRequirement: CodeBlock { } else { paramList = FunctionParameterListSyntax( parameters.enumerated().compactMap { index, param in - guard !param.name.isEmpty, !param.type.isEmpty else { + guard !param.name.isEmpty else { return nil } var paramSyntax = FunctionParameterSyntax( @@ -95,7 +95,7 @@ public struct FunctionRequirement: CodeBlock { ? .wildcardToken(trailingTrivia: .space) : .identifier(param.name), secondName: param.isUnnamed ? .identifier(param.name) : nil, colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(param.type)), + type: param.type.typeSyntax, defaultValue: param.defaultValue.map { InitializerClauseSyntax( equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), diff --git a/Sources/SyntaxKit/Parameters/Parameter.swift b/Sources/SyntaxKit/Parameters/Parameter.swift index 7055911..b416a06 100644 --- a/Sources/SyntaxKit/Parameters/Parameter.swift +++ b/Sources/SyntaxKit/Parameters/Parameter.swift @@ -41,7 +41,7 @@ public struct Parameter: CodeBlock { /// If the label is the underscore character "_", the parameter is treated as unnamed. internal let label: String? - internal let type: String + internal let type: TypeRepresentable internal let defaultValue: String? /// Convenience flag – true when the parameter uses the underscore label. @@ -90,7 +90,7 @@ public struct Parameter: CodeBlock { } /// Creates a single-name parameter (same label and internal name). - public init(name: String, type: String, defaultValue: String? = nil) { + public init(name: String, type: TypeRepresentable, defaultValue: String? = nil) { self.name = name self.label = nil self.type = type @@ -103,7 +103,7 @@ public struct Parameter: CodeBlock { public init( _ internalName: String, labeled externalLabel: String, - type: String, + type: TypeRepresentable, defaultValue: String? = nil ) { self.name = internalName @@ -113,7 +113,8 @@ public struct Parameter: CodeBlock { } /// Creates an unlabeled (anonymous) parameter using the underscore label. - public init(unlabeled internalName: String, type: String, defaultValue: String? = nil) { + public init(unlabeled internalName: String, type: TypeRepresentable, defaultValue: String? = nil) + { self.name = internalName self.label = "_" self.type = type @@ -123,7 +124,7 @@ public struct Parameter: CodeBlock { /// Deprecated: retains source compatibility with earlier API that used an `isUnnamed` flag. /// Prefer `Parameter(unlabeled:type:)` or the new labelled initialisers. @available(*, deprecated, message: "Use Parameter(unlabeled:type:) or Parameter(_:labeled:type:)") - public init(name: String, type: String, defaultValue: String? = nil, isUnnamed: Bool) { + public init(name: String, type: TypeRepresentable, defaultValue: String? = nil, isUnnamed: Bool) { if isUnnamed { self.init(unlabeled: name, type: type, defaultValue: defaultValue) } else { diff --git a/Sources/SyntaxKit/Parameters/ParameterExp.swift b/Sources/SyntaxKit/Parameters/ParameterExp.swift index 90539a8..66c5876 100644 --- a/Sources/SyntaxKit/Parameters/ParameterExp.swift +++ b/Sources/SyntaxKit/Parameters/ParameterExp.swift @@ -66,15 +66,30 @@ public struct ParameterExp: CodeBlock { public var syntax: SyntaxProtocol { if name.isEmpty { - return value.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + if let exprBlock = value as? ExprCodeBlock { + return exprBlock.exprSyntax + } else { + return value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } } else { + let expression: ExprSyntax + if let exprBlock = value as? ExprCodeBlock { + expression = exprBlock.exprSyntax + } else { + expression = + value.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } return LabeledExprSyntax( label: .identifier(name), - colon: .colonToken(), - expression: value.syntax.as(ExprSyntax.self) - ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + colon: .colonToken(trailingTrivia: .init()), + expression: expression ) } } + + internal var isUnlabeledClosure: Bool { + name.isEmpty && value is Closure + } } diff --git a/Sources/SyntaxKit/parser/SourceRange.swift b/Sources/SyntaxKit/Parser/SourceRange.swift similarity index 97% rename from Sources/SyntaxKit/parser/SourceRange.swift rename to Sources/SyntaxKit/Parser/SourceRange.swift index c29b2ce..cc5dfc6 100644 --- a/Sources/SyntaxKit/parser/SourceRange.swift +++ b/Sources/SyntaxKit/Parser/SourceRange.swift @@ -37,7 +37,7 @@ internal struct SourceRange: Codable, Equatable { } extension SourceRange: CustomStringConvertible { - var description: String { + internal var description: String { """ { startRow: \(startRow) diff --git a/Sources/SyntaxKit/parser/String+Extensions.swift b/Sources/SyntaxKit/Parser/String+Extensions.swift similarity index 100% rename from Sources/SyntaxKit/parser/String+Extensions.swift rename to Sources/SyntaxKit/Parser/String+Extensions.swift diff --git a/Sources/SyntaxKit/parser/String.swift b/Sources/SyntaxKit/Parser/String.swift similarity index 100% rename from Sources/SyntaxKit/parser/String.swift rename to Sources/SyntaxKit/Parser/String.swift diff --git a/Sources/SyntaxKit/parser/StructureProperty.swift b/Sources/SyntaxKit/Parser/StructureProperty.swift similarity index 93% rename from Sources/SyntaxKit/parser/StructureProperty.swift rename to Sources/SyntaxKit/Parser/StructureProperty.swift index 5c5f72e..59dfb23 100644 --- a/Sources/SyntaxKit/parser/StructureProperty.swift +++ b/Sources/SyntaxKit/Parser/StructureProperty.swift @@ -34,7 +34,7 @@ internal struct StructureProperty: Codable, Equatable { internal let value: StructureValue? internal let ref: String? - init(name: String, value: StructureValue? = nil, ref: String? = nil) { + internal init(name: String, value: StructureValue? = nil, ref: String? = nil) { self.name = name.escapeHTML() self.value = value self.ref = ref?.escapeHTML() @@ -42,7 +42,7 @@ internal struct StructureProperty: Codable, Equatable { } extension StructureProperty: CustomStringConvertible { - var description: String { + internal var description: String { """ { name: \(name) diff --git a/Sources/SyntaxKit/parser/StructureValue.swift b/Sources/SyntaxKit/Parser/StructureValue.swift similarity index 94% rename from Sources/SyntaxKit/parser/StructureValue.swift rename to Sources/SyntaxKit/Parser/StructureValue.swift index 63aa525..ac4ba50 100644 --- a/Sources/SyntaxKit/parser/StructureValue.swift +++ b/Sources/SyntaxKit/Parser/StructureValue.swift @@ -33,14 +33,14 @@ internal struct StructureValue: Codable, Equatable { internal let text: String internal let kind: String? - init(text: String, kind: String? = nil) { + internal init(text: String, kind: String? = nil) { self.text = text.escapeHTML().replaceHTMLWhitespacesToSymbols() self.kind = kind?.escapeHTML() } } extension StructureValue: CustomStringConvertible { - var description: String { + internal var description: String { """ { text: \(text) diff --git a/Sources/SyntaxKit/parser/SyntaxParser.swift b/Sources/SyntaxKit/Parser/SyntaxParser.swift similarity index 100% rename from Sources/SyntaxKit/parser/SyntaxParser.swift rename to Sources/SyntaxKit/Parser/SyntaxParser.swift diff --git a/Sources/SyntaxKit/parser/SyntaxResponse.swift b/Sources/SyntaxKit/Parser/SyntaxResponse.swift similarity index 100% rename from Sources/SyntaxKit/parser/SyntaxResponse.swift rename to Sources/SyntaxKit/Parser/SyntaxResponse.swift diff --git a/Sources/SyntaxKit/parser/SyntaxType.swift b/Sources/SyntaxKit/Parser/SyntaxType.swift similarity index 100% rename from Sources/SyntaxKit/parser/SyntaxType.swift rename to Sources/SyntaxKit/Parser/SyntaxType.swift diff --git a/Sources/SyntaxKit/parser/Token.swift b/Sources/SyntaxKit/Parser/Token.swift similarity index 93% rename from Sources/SyntaxKit/parser/Token.swift rename to Sources/SyntaxKit/Parser/Token.swift index 48c0729..d52a04c 100644 --- a/Sources/SyntaxKit/parser/Token.swift +++ b/Sources/SyntaxKit/Parser/Token.swift @@ -34,7 +34,7 @@ internal struct Token: Codable, Equatable { internal var leadingTrivia: String internal var trailingTrivia: String - init(kind: String, leadingTrivia: String, trailingTrivia: String) { + internal init(kind: String, leadingTrivia: String, trailingTrivia: String) { self.kind = kind.escapeHTML() self.leadingTrivia = leadingTrivia self.trailingTrivia = trailingTrivia @@ -42,7 +42,7 @@ internal struct Token: Codable, Equatable { } extension Token: CustomStringConvertible { - var description: String { + internal var description: String { """ { kind: \(kind) diff --git a/Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift b/Sources/SyntaxKit/Parser/TokenVisitor+Helpers.swift similarity index 96% rename from Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift rename to Sources/SyntaxKit/Parser/TokenVisitor+Helpers.swift index 4c20266..b95abb3 100644 --- a/Sources/SyntaxKit/parser/TokenVisitor+Helpers.swift +++ b/Sources/SyntaxKit/Parser/TokenVisitor+Helpers.swift @@ -31,7 +31,7 @@ import Foundation import SwiftSyntax extension TokenVisitor { - func processToken(_ token: TokenSyntax) { + internal func processToken(_ token: TokenSyntax) { var kind = "\(token.tokenKind)" if let index = kind.firstIndex(of: "(") { kind = String(kind.prefix(upTo: index)) @@ -46,7 +46,7 @@ extension TokenVisitor { let text = token.presence == .present || showMissingTokens ? token.text : "" } - func processTriviaPiece(_ piece: TriviaPiece) -> String { + internal func processTriviaPiece(_ piece: TriviaPiece) -> String { func wrapWithSpanTag(class className: String, text: String) -> String { " Bool { + internal static func == (lhs: TreeNode, rhs: TreeNode) -> Bool { lhs.id == rhs.id && lhs.parent == rhs.parent && lhs.text == rhs.text && lhs.range == rhs.range && lhs.structure == rhs.structure && lhs.type == rhs.type && lhs.token == rhs.token } } extension TreeNode: CustomStringConvertible { - var description: String { + internal var description: String { """ { id: \(id) diff --git a/Sources/SyntaxKit/Utilities/EnumCase+Syntax.swift b/Sources/SyntaxKit/Utilities/EnumCase+Syntax.swift index d122bf8..ea996e2 100644 --- a/Sources/SyntaxKit/Utilities/EnumCase+Syntax.swift +++ b/Sources/SyntaxKit/Utilities/EnumCase+Syntax.swift @@ -34,100 +34,58 @@ extension EnumCase { /// When used in expressions (throw, return, if bodies), returns expression syntax. /// When used in declarations (enum cases), returns declaration syntax. public var syntax: SyntaxProtocol { - // Check if we're in an expression context by looking at the call stack - // For now, we'll use a heuristic: if this is being used in a context that expects expressions, - // we'll return the expression syntax. Otherwise, we'll return the declaration syntax. - - // Since we can't easily determine context from here, we'll provide both options - // and let the calling code choose. For now, we'll default to declaration syntax - // and let specific contexts (like Throw) handle the conversion. - + // For enum case declarations, return EnumCaseDeclSyntax let caseKeyword = TokenSyntax.keyword(.case, trailingTrivia: .space) - let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) - var parameterClause: EnumCaseParameterClauseSyntax? - if !associatedValues.isEmpty { - let parameters = EnumCaseParameterListSyntax( - associatedValues.map { associated in - EnumCaseParameterSyntax( - firstName: .identifier(associated.name), - secondName: .identifier(associated.name), - colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), - type: TypeSyntax(IdentifierTypeSyntax(name: .identifier(associated.type))) - ) - } - ) - parameterClause = EnumCaseParameterClauseSyntax( - leftParen: .leftParenToken(), - parameters: parameters, - rightParen: .rightParenToken() - ) - } + // Create the enum case element + var enumCaseElement = EnumCaseElementSyntax( + name: .identifier(name, trailingTrivia: .space) + ) - var initializer: InitializerClauseSyntax? - if let literal = literalValue { - switch literal { - case .string(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment(StringSegmentSyntax(content: .stringSegment(value))) - ]), - closingQuote: .stringQuoteToken() - ) - ) - case .float(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: FloatLiteralExprSyntax(literal: .floatLiteral(String(value))) - ) - case .integer(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: IntegerLiteralExprSyntax(digits: .integerLiteral(String(value))) - ) - case .nil: - initializer = InitializerClauseSyntax( + // Add raw value if present + if let literalValue = literalValue { + let valueSyntax = + literalValue.syntax.as(ExprSyntax.self) + ?? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + enumCaseElement = enumCaseElement.with( + \.rawValue, + .init( equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: NilLiteralExprSyntax(nilKeyword: .keyword(.nil)) + value: valueSyntax ) - case .boolean(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: BooleanLiteralExprSyntax(literal: value ? .keyword(.true) : .keyword(.false)) - ) - case .ref(let value): - initializer = InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: DeclReferenceExprSyntax(baseName: .identifier(value)) + ) + } + + // Add associated values if present + if !associatedValues.isEmpty { + let parameters = associatedValues.enumerated().map { index, associated in + var parameter = EnumCaseParameterSyntax( + firstName: nil, + secondName: .identifier(associated.name), + colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), + type: TypeSyntax(IdentifierTypeSyntax(name: .identifier(associated.type))) ) - case .tuple: - fatalError("Tuple is not supported as a raw value for enum cases.") - case .array: - fatalError("Array is not supported as a raw value for enum cases.") - case .dictionary: - fatalError("Dictionary is not supported as a raw value for enum cases.") + + if index < associatedValues.count - 1 { + parameter = parameter.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + + return parameter } + + enumCaseElement = enumCaseElement.with( + \.parameterClause, + .init( + leftParen: .leftParenToken(), + parameters: EnumCaseParameterListSyntax(parameters), + rightParen: .rightParenToken() + ) + ) } return EnumCaseDeclSyntax( caseKeyword: caseKeyword, - elements: EnumCaseElementListSyntax([ - EnumCaseElementSyntax( - leadingTrivia: .space, - _: nil, - name: identifier, - _: nil, - parameterClause: parameterClause, - _: nil, - rawValue: initializer, - _: nil, - trailingComma: nil, - trailingTrivia: .newline - ) - ]) + elements: EnumCaseElementListSyntax([enumCaseElement]) ) } } diff --git a/Sources/SyntaxKit/Utilities/EnumCase.swift b/Sources/SyntaxKit/Utilities/EnumCase.swift index 5588426..371db7b 100644 --- a/Sources/SyntaxKit/Utilities/EnumCase.swift +++ b/Sources/SyntaxKit/Utilities/EnumCase.swift @@ -92,6 +92,17 @@ public struct EnumCase: CodeBlock { /// Returns a SwiftSyntax expression for this enum case (for use in throw/return/etc). public var asExpressionSyntax: ExprSyntax { let parts = name.split(separator: ".", maxSplits: 1) + let hasAssociated = !associatedValues.isEmpty + if parts.count == 1 && !hasAssociated { + // Only a case name, no type, no associated values: generate `.caseName` + return ExprSyntax( + MemberAccessExprSyntax( + base: nil as ExprSyntax?, + dot: .periodToken(), + name: .identifier(name) + ) + ) + } let base: ExprSyntax? = parts.count == 2 ? ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(String(parts[0])))) @@ -99,10 +110,10 @@ public struct EnumCase: CodeBlock { let caseName = parts.count == 2 ? String(parts[1]) : name let memberAccess = MemberAccessExprSyntax( base: base, - dot: .periodToken(), - name: .identifier(caseName) + period: .periodToken(), + declName: DeclReferenceExprSyntax(baseName: .identifier(caseName)) ) - if !associatedValues.isEmpty { + if hasAssociated { let tuple = TupleExprSyntax( leftParen: .leftParenToken(), elements: TupleExprElementListSyntax( diff --git a/Sources/SyntaxKit/Variables/ComputedProperty.swift b/Sources/SyntaxKit/Variables/ComputedProperty.swift index 2322642..7b6cdb6 100644 --- a/Sources/SyntaxKit/Variables/ComputedProperty.swift +++ b/Sources/SyntaxKit/Variables/ComputedProperty.swift @@ -34,18 +34,36 @@ public struct ComputedProperty: CodeBlock { private let name: String private let type: String private let body: [CodeBlock] + private var accessModifier: String? + private let explicitType: Bool /// Creates a computed property declaration. /// - Parameters: /// - name: The name of the property. /// - type: The type of the property. + /// - explicitType: Whether the type should be explicitly marked. /// - content: A ``CodeBlockBuilder`` that provides the body of the getter. - public init(_ name: String, type: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + public init( + _ name: String, + type: String, + explicitType: Bool = true, + @CodeBlockBuilderResult _ content: () -> [CodeBlock] + ) { self.name = name self.type = type + self.explicitType = explicitType self.body = content() } + /// Sets the access modifier for the computed property declaration. + /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Returns: A copy of the computed property with the access modifier set. + public func access(_ access: String) -> Self { + var copy = self + copy.accessModifier = access + return copy + } + public var syntax: SyntaxProtocol { let accessor = AccessorBlockSyntax( leftBrace: TokenSyntax.leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), @@ -66,12 +84,38 @@ public struct ComputedProperty: CodeBlock { ), rightBrace: TokenSyntax.rightBraceToken(leadingTrivia: .newline) ) - let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) + let identifier = TokenSyntax.identifier( + name, + trailingTrivia: explicitType ? (.space + .space) : .space + ) let typeAnnotation = TypeAnnotationSyntax( - colon: TokenSyntax.colonToken(leadingTrivia: .space, trailingTrivia: .space), + colon: TokenSyntax.colonToken(trailingTrivia: .space), type: IdentifierTypeSyntax(name: .identifier(type)) ) + + // Build modifiers + var modifiers: DeclModifierListSyntax = [] + if let access = accessModifier { + let keyword: Keyword + switch access { + case "public": + keyword = .public + case "private": + keyword = .private + case "internal": + keyword = .internal + case "fileprivate": + keyword = .fileprivate + default: + keyword = .public // fallback + } + modifiers = DeclModifierListSyntax([ + DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + ]) + } + return VariableDeclSyntax( + modifiers: modifiers, bindingSpecifier: TokenSyntax.keyword(.var, trailingTrivia: .space), bindings: PatternBindingListSyntax([ PatternBindingSyntax( diff --git a/Sources/SyntaxKit/Variables/Variable+Attributes.swift b/Sources/SyntaxKit/Variables/Variable+Attributes.swift new file mode 100644 index 0000000..4b534f9 --- /dev/null +++ b/Sources/SyntaxKit/Variables/Variable+Attributes.swift @@ -0,0 +1,108 @@ +// +// Variable+Attributes.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Represents attribute arguments for variable declarations. +private struct AttributeArguments { + let leftParen: TokenSyntax? + let rightParen: TokenSyntax? + let arguments: AttributeSyntax.Arguments? + + init( + leftParen: TokenSyntax? = nil, + rightParen: TokenSyntax? = nil, + arguments: AttributeSyntax.Arguments? = nil + ) { + self.leftParen = leftParen + self.rightParen = rightParen + self.arguments = arguments + } +} + +extension Variable { + /// Builds the attribute list for the variable declaration. + internal func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { + guard !attributes.isEmpty else { + return AttributeListSyntax([]) + } + + let attributeElements = attributes.map(buildAttributeElement) + return AttributeListSyntax(attributeElements) + } + + /// Builds an attribute element from attribute info. + private func buildAttributeElement(from attributeInfo: AttributeInfo) + -> AttributeListSyntax.Element + { + let attributeArgs = buildAttributeArguments(from: attributeInfo.arguments) + + return AttributeListSyntax.Element( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), + leftParen: attributeArgs.leftParen, + arguments: attributeArgs.arguments, + rightParen: attributeArgs.rightParen + ) + ) + } + + /// Builds attribute arguments from a string array. + private func buildAttributeArguments(from arguments: [String]) -> AttributeArguments { + guard !arguments.isEmpty else { + return AttributeArguments() + } + + let leftParen: TokenSyntax = .leftParenToken() + let rightParen: TokenSyntax = .rightParenToken() + + let argumentList = arguments.map { argument in + DeclReferenceExprSyntax(baseName: .identifier(argument)) + } + + let argumentsSyntax = AttributeSyntax.Arguments.argumentList( + LabeledExprListSyntax( + argumentList.enumerated().map { index, expr in + var element = LabeledExprSyntax(expression: ExprSyntax(expr)) + if index < argumentList.count - 1 { + element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) + } + return element + } + ) + ) + + return AttributeArguments( + leftParen: leftParen, + rightParen: rightParen, + arguments: argumentsSyntax + ) + } +} diff --git a/Sources/SyntaxKit/Variables/Variable+Modifiers.swift b/Sources/SyntaxKit/Variables/Variable+Modifiers.swift new file mode 100644 index 0000000..cdbf079 --- /dev/null +++ b/Sources/SyntaxKit/Variables/Variable+Modifiers.swift @@ -0,0 +1,80 @@ +// +// Variable+Modifiers.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +extension Variable { + /// Builds the modifiers for the variable declaration. + internal func buildModifiers() -> DeclModifierListSyntax { + var modifiers: [DeclModifierSyntax] = [] + + if isStatic { + modifiers.append(buildStaticModifier()) + } + + if isAsync { + modifiers.append(buildAsyncModifier()) + } + + if let access = accessModifier { + modifiers.append(buildAccessModifier(access)) + } + + return DeclModifierListSyntax(modifiers) + } + + /// Builds a static modifier. + private func buildStaticModifier() -> DeclModifierSyntax { + DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) + } + + /// Builds an async modifier. + private func buildAsyncModifier() -> DeclModifierSyntax { + DeclModifierSyntax(name: .keyword(.async, trailingTrivia: .space)) + } + + /// Builds an access modifier. + private func buildAccessModifier(_ access: String) -> DeclModifierSyntax { + let keyword: Keyword + switch access { + case "public": + keyword = .public + case "private": + keyword = .private + case "internal": + keyword = .internal + case "fileprivate": + keyword = .fileprivate + default: + keyword = .public // fallback + } + + return DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + } +} diff --git a/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift b/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift index b84e5d6..e295ce1 100644 --- a/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift +++ b/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift @@ -169,5 +169,29 @@ extension Variable { explicitType: explicitType ?? true ) } + + /// Creates a `let` or `var` declaration with an explicit type (TypeRepresentable). + /// - Parameters: + /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. + /// - name: The name of the variable. + /// - type: The type of the variable (TypeRepresentable). + /// - equals: The initial value expression of the variable, if any. + /// - explicitType: Whether the variable has an explicit type. + public init( + _ kind: VariableKind, + name: String, + type: TypeRepresentable, + equals defaultValue: CodeBlock? = nil, + explicitType: Bool? = nil + ) { + let finalExplicitType = explicitType ?? (defaultValue == nil) + self.init( + kind: kind, + name: name, + type: type, + defaultValue: defaultValue, + explicitType: finalExplicitType + ) + } } // swiftlint:enable discouraged_optional_boolean diff --git a/Sources/SyntaxKit/Variables/Variable.swift b/Sources/SyntaxKit/Variables/Variable.swift index 7b89b5f..c0cda6a 100644 --- a/Sources/SyntaxKit/Variables/Variable.swift +++ b/Sources/SyntaxKit/Variables/Variable.swift @@ -34,12 +34,13 @@ import SwiftSyntax public struct Variable: CodeBlock { private let kind: VariableKind private let name: String - private let type: String + private let type: TypeRepresentable private let defaultValue: CodeBlock? - private var isStatic: Bool = false - private var isAsync: Bool = false + internal var isStatic: Bool = false + internal var isAsync: Bool = false private var attributes: [AttributeInfo] = [] private var explicitType: Bool = false + internal var accessModifier: String? /// Internal initializer used by extension initializers to reduce code duplication. /// - Parameters: @@ -51,14 +52,12 @@ public struct Variable: CodeBlock { internal init( kind: VariableKind, name: String, - type: String? = nil, + type: TypeRepresentable? = nil, defaultValue: CodeBlock? = nil, explicitType: Bool = false ) { self.kind = kind self.name = name - - // If type is provided, use it; otherwise try to infer from defaultValue if let providedType = type { self.type = providedType } else if let initValue = defaultValue as? Init { @@ -66,7 +65,6 @@ public struct Variable: CodeBlock { } else { self.type = "" } - self.defaultValue = defaultValue self.explicitType = explicitType } @@ -87,6 +85,15 @@ public struct Variable: CodeBlock { return copy } + /// Sets the access modifier for the variable declaration. + /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Returns: A copy of the variable with the access modifier set. + public func access(_ access: String) -> Self { + var copy = self + copy.accessModifier = access + return copy + } + /// Adds an attribute to the variable declaration. /// - Parameters: /// - attribute: The attribute name (without the @ symbol). @@ -105,41 +112,12 @@ public struct Variable: CodeBlock { } public var syntax: SyntaxProtocol { - let bindingKeyword = TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) - let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) - let typeAnnotation: TypeAnnotationSyntax? = - (explicitType && !type.isEmpty) - ? TypeAnnotationSyntax( - colon: .colonToken(leadingTrivia: .space, trailingTrivia: .space), - type: IdentifierTypeSyntax(name: .identifier(type)) - ) : nil - let initializer = defaultValue.map { value in - let expr: ExprSyntax - if let exprBlock = value as? ExprCodeBlock { - expr = exprBlock.exprSyntax - } else if let exprSyntax = value.syntax.as(ExprSyntax.self) { - expr = exprSyntax - } else { - expr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) - } - return InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: expr - ) - } - var modifiers: DeclModifierListSyntax = [] - if isStatic { - modifiers = DeclModifierListSyntax([ - DeclModifierSyntax(name: .keyword(.static, trailingTrivia: .space)) - ]) - } - if isAsync { - modifiers = DeclModifierListSyntax( - modifiers + [ - DeclModifierSyntax(name: .keyword(.async, trailingTrivia: .space)) - ] - ) - } + let bindingKeyword = buildBindingKeyword() + let identifier = buildIdentifier() + let typeAnnotation = buildTypeAnnotation() + let initializer = buildInitializer() + let modifiers = buildModifiers() + return VariableDeclSyntax( attributes: buildAttributeList(from: attributes), modifiers: modifiers, @@ -154,62 +132,51 @@ public struct Variable: CodeBlock { ) } - private func buildAttributeList(from attributes: [AttributeInfo]) -> AttributeListSyntax { - if attributes.isEmpty { - return AttributeListSyntax([]) + // MARK: - Private Helper Methods + + private func buildBindingKeyword() -> TokenSyntax { + TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) + } + + private func buildIdentifier() -> TokenSyntax { + TokenSyntax.identifier( + name, + trailingTrivia: explicitType ? (.space + .space) : .space + ) + } + + private func buildTypeAnnotation() -> TypeAnnotationSyntax? { + let shouldShowType = explicitType && !(type is String && (type as? String)?.isEmpty != false) + guard shouldShowType else { + return nil } - let attributeElements = attributes.map { attributeInfo in - let arguments = attributeInfo.arguments - - var leftParen: TokenSyntax? - var rightParen: TokenSyntax? - var argumentsSyntax: AttributeSyntax.Arguments? - - if !arguments.isEmpty { - leftParen = .leftParenToken() - rightParen = .rightParenToken() - - let argumentList = arguments.map { argument in - DeclReferenceExprSyntax(baseName: .identifier(argument)) - } - - argumentsSyntax = .argumentList( - LabeledExprListSyntax( - argumentList.enumerated().map { index, expr in - var element = LabeledExprSyntax(expression: ExprSyntax(expr)) - if index < argumentList.count - 1 { - element = element.with(\.trailingComma, .commaToken(trailingTrivia: .space)) - } - return element - } - ) - ) - } - - return AttributeListSyntax.Element( - AttributeSyntax( - atSign: .atSignToken(), - attributeName: IdentifierTypeSyntax(name: .identifier(attributeInfo.name)), - leftParen: leftParen, - arguments: argumentsSyntax, - rightParen: rightParen - ) - ) + return TypeAnnotationSyntax( + colon: .colonToken(trailingTrivia: .space), + type: type.typeSyntax + ) + } + + private func buildInitializer() -> InitializerClauseSyntax? { + guard let defaultValue = defaultValue else { + return nil } - return AttributeListSyntax(attributeElements) + let expr = buildExpressionFromValue(defaultValue) + + return InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: expr + ) } - public enum VariableKind { - case `var` - case `let` - case `static` - case `lazy` - case `weak` - case `unowned` - case `final` - case `override` - case `mutating` + private func buildExpressionFromValue(_ value: CodeBlock) -> ExprSyntax { + if let exprBlock = value as? ExprCodeBlock { + return exprBlock.exprSyntax + } else if let exprSyntax = value.syntax.as(ExprSyntax.self) { + return exprSyntax + } else { + return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + } } } diff --git a/Sources/SyntaxKit/Variables/VariableExp.swift b/Sources/SyntaxKit/Variables/VariableExp.swift index 8e559aa..30d73c2 100644 --- a/Sources/SyntaxKit/Variables/VariableExp.swift +++ b/Sources/SyntaxKit/Variables/VariableExp.swift @@ -64,6 +64,19 @@ public struct VariableExp: CodeBlock, PatternConvertible { FunctionCallExp(baseName: name, methodName: methodName, parameters: params()) } + /// Creates a reference to this variable. + /// - Parameter referenceType: The type of reference (e.g., "weak", "unowned"). + /// - Returns: A reference expression. + public func reference(_ referenceType: String) -> CodeBlock { + ReferenceExp(base: self, referenceType: referenceType) + } + + /// Creates an optional chaining expression for this variable. + /// - Returns: An optional chaining expression. + public func optional() -> CodeBlock { + OptionalChainingExp(base: self) + } + public var syntax: SyntaxProtocol { ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) } diff --git a/Tests/SyntaxKitTests/Integration/BlackjackTests.swift b/Tests/SyntaxKitTests/Integration/BlackjackTests.swift index ee51ff2..740f218 100644 --- a/Tests/SyntaxKitTests/Integration/BlackjackTests.swift +++ b/Tests/SyntaxKitTests/Integration/BlackjackTests.swift @@ -62,10 +62,9 @@ internal struct BlackjackTests { } """ - // Normalize whitespace, remove comments and modifiers, and normalize colon spacing - let normalizedGenerated = syntax.syntax.description.normalize() - - let normalizedExpected = expected.normalize() + // Use structural comparison to focus on code structure rather than formatting + let normalizedGenerated = syntax.syntax.description.normalizeStructural() + let normalizedExpected = expected.normalizeStructural() #expect(normalizedGenerated == normalizedExpected) } @@ -200,10 +199,9 @@ internal struct BlackjackTests { } """ - // Normalize whitespace, remove comments and modifiers, and normalize colon spacing - let normalizedGenerated = syntax.syntax.description.normalize() - - let normalizedExpected = expected.normalize() + // Use structural comparison to focus on code structure rather than formatting + let normalizedGenerated = syntax.syntax.description.normalizeStructural() + let normalizedExpected = expected.normalizeStructural() #expect(normalizedGenerated == normalizedExpected) } diff --git a/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift b/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift new file mode 100644 index 0000000..9edf180 --- /dev/null +++ b/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift @@ -0,0 +1,192 @@ +// +// SwiftUIExampleTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import Testing + +@testable import SyntaxKit + +@Suite internal struct SwiftUIExampleTests { + @Test("SwiftUI example DSL generates expected Swift code") + internal func testSwiftUIExample() throws { + // Test the onToggle variable with closure type and attributes + let onToggleVariable = Variable(.let, name: "onToggle", type: "(Date) -> Void") + .access("private") + + let generatedCode = onToggleVariable.generateCode() + #expect(generatedCode.contains("private let onToggle")) + #expect(generatedCode.contains("(Date) -> Void")) + } + + @Test("SwiftUI example with complex closure and capture list") + internal func testSwiftUIComplexClosure() throws { + // Test the Task with closure that has capture list and attributes + let taskClosure = Closure( + capture: { + ParameterExp(unlabeled: VariableExp("self")) + }, + body: { + VariableExp("self").call("onToggle") { + ParameterExp(unlabeled: Init("Date")) + } + } + ) + + let generatedCode = taskClosure.generateCode() + #expect(generatedCode.contains("self")) + #expect(generatedCode.contains("onToggle")) + #expect(generatedCode.contains("Date()")) + } + + @Test("SwiftUI TodoItemRow DSL generates expected Swift code") + internal func testSwiftUITodoItemRowExample() throws { + // Use the full DSL from Examples/Completed/swiftui/dsl.swift + let dsl = Group { + Import("SwiftUI").access("public") + + Struct("TodoItemRow") { + Variable(.let, name: "item", type: "TodoItem").access("private") + + Variable( + .let, + name: "onToggle", + type: + ClosureType(returns: "Void") { + ClosureParameter("Date") + } + .attribute("MainActor") + .attribute("Sendable") + ) + .access("private") + + ComputedProperty("body", type: "some View") { + Init("HStack") { + ParameterExp( + unlabeled: Closure { + ParameterExp( + unlabeled: Closure { + Init("Button") { + ParameterExp(name: "action", value: VariableExp("onToggle")) + ParameterExp( + unlabeled: Closure { + Init("Image") { + ParameterExp( + name: "systemName", + value: ConditionalOp( + if: VariableExp("item").property("isCompleted"), + then: Literal.string("checkmark.circle.fill"), + else: Literal.string("circle") + ) + ) + }.call("foregroundColor") { + ParameterExp( + unlabeled: ConditionalOp( + if: VariableExp("item").property("isCompleted"), + then: EnumCase("green"), + else: EnumCase("gray") + ) + ) + } + } + ) + } + Init("Button") { + ParameterExp( + name: "action", + value: Closure { + Init("Task") { + ParameterExp( + unlabeled: Closure( + capture: { + ParameterExp(unlabeled: VariableExp("self").reference("weak")) + }, + body: { + VariableExp("self").optional().call("onToggle") { + ParameterExp(unlabeled: Init("Date")) + } + } + ) + .attribute("MainActor") + ) + } + } + ) + ParameterExp( + unlabeled: Closure { + Init("Image") { + ParameterExp(name: "systemName", value: Literal.string("trash")) + } + } + ) + } + } + ) + } + ) + } + } + .access("public") + } + .inherits("View") + .access("public") + } + + // Expected Swift code from Examples/Completed/swiftui/code.swift + let expectedCode = """ + public import SwiftUI + + public struct TodoItemRow: View { + private let item: TodoItem + private let onToggle: @MainActor @Sendable (Date) -> Void + + public var body: some View { + HStack { + Button(action: onToggle) { + Image(systemName: item.isCompleted ? "checkmark.circle.fill" : "circle") + .foregroundColor(item.isCompleted ? .green : .gray) + } + + Button(action: { + Task { @MainActor [weak self] in + self?.onToggle(Date()) + } + }) { + Image(systemName: "trash") + } + } + } + } + """ + + // Generate code from DSL + let generated = dsl.generateCode().normalizeFlexible() + let expected = expectedCode.normalizeFlexible() + #expect(generated == expected) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Declarations/StructTests.swift b/Tests/SyntaxKitTests/Unit/Declarations/StructTests.swift index 7ea5bf8..75d6658 100644 --- a/Tests/SyntaxKitTests/Unit/Declarations/StructTests.swift +++ b/Tests/SyntaxKitTests/Unit/Declarations/StructTests.swift @@ -58,8 +58,8 @@ internal struct StructTests { } """ - let normalizedGenerated = stackStruct.generateCode().normalize() - let normalizedExpected = expectedCode.normalize() + let normalizedGenerated = stackStruct.generateCode().normalizeStructural() + let normalizedExpected = expectedCode.normalizeStructural() #expect(normalizedGenerated == normalizedExpected) } @@ -74,8 +74,8 @@ internal struct StructTests { } """ - let normalizedGenerated = containerStruct.generateCode().normalize() - let normalizedExpected = expectedCode.normalize() + let normalizedGenerated = containerStruct.generateCode().normalizeStructural() + let normalizedExpected = expectedCode.normalizeStructural() #expect(normalizedGenerated == normalizedExpected) } @@ -92,8 +92,8 @@ internal struct StructTests { } """ - let normalizedGenerated = simpleStruct.generateCode().normalize() - let normalizedExpected = expectedCode.normalize() + let normalizedGenerated = simpleStruct.generateCode().normalizeStructural() + let normalizedExpected = expectedCode.normalizeStructural() #expect(normalizedGenerated == normalizedExpected) } } diff --git a/Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift b/Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift index ecf8694..074c234 100644 --- a/Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift +++ b/Tests/SyntaxKitTests/Unit/ErrorHandling/ErrorHandlingTests.swift @@ -66,12 +66,13 @@ import Testing } """ - #expect( - generated.normalize() == expected.normalize() - ) - - print("Generated code:") - print(generated) + let normalizedGenerated = generated.replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "\n", with: "") + let normalizedExpected = + expected + .replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "\n", with: "") + #expect(normalizedGenerated.contains(normalizedExpected)) } // swiftlint:enable function_body_length diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift new file mode 100644 index 0000000..d913c4d --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift @@ -0,0 +1,104 @@ +// +// ClosureCaptureCoverageTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for improving code coverage of Closure+Capture functionality. +/// +/// This test suite focuses on testing edge cases and uncovered code paths +/// in the Closure+Capture extension file to ensure comprehensive test coverage. +internal final class ClosureCaptureCoverageTests { + // MARK: - Closure+Capture.swift Coverage Tests + + /// Tests fallback cases in CaptureInfo initializers. + @Test("Capture info fallback cases") + internal func testCaptureInfoFallbackCases() { + // Test fallback cases in CaptureInfo initializers + + // Test with unknown reference type (should fallback to weak) + let unknownRef = ReferenceExp(base: VariableExp("self"), referenceType: "unknown") + let paramWithUnknownRef = ParameterExp(name: "self", value: unknownRef) + let closure = Closure( + capture: { paramWithUnknownRef }, + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Should fallback to weak + #expect(description.contains("[weak self]")) + } + + /// Tests CaptureInfo with non-VariableExp capture expression. + @Test("Capture info with non VariableExp") + internal func testCaptureInfoWithNonVariableExp() { + // Test CaptureInfo with non-VariableExp capture expression + let initBlock = Init("String") + let ref = ReferenceExp(base: initBlock, referenceType: "weak") + let param = ParameterExp(name: "self", value: ref) + let closure = Closure( + capture: { param }, + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Should fallback to "self" + #expect(description.contains("[weak self]")) + } + + /// Tests CaptureInfo with non-VariableExp parameter value. + @Test("Capture info with non VariableExp parameter") + internal func testCaptureInfoWithNonVariableExpParameter() { + // Test CaptureInfo with non-VariableExp parameter value + let initBlock = Init("String") + let param = ParameterExp(name: "self", value: initBlock) + let closure = Closure( + capture: { param }, + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Should fallback to "self" + #expect(description.contains("[self]")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ClosureCoverageTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ClosureCoverageTests.swift new file mode 100644 index 0000000..a5ebb73 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ClosureCoverageTests.swift @@ -0,0 +1,221 @@ +// +// ClosureCoverageTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for improving code coverage of Closure-related functionality. +/// +/// This test suite focuses on testing edge cases and uncovered code paths +/// in the Closure extension files to ensure comprehensive test coverage. +internal final class ClosureCoverageTests { + // MARK: - Closure+Body.swift Coverage Tests + + /// Tests the DeclSyntax case in buildBodyItem method. + @Test("Build body item with DeclSyntax") + internal func testBuildBodyItemWithDeclSyntax() { + // Test the DeclSyntax case in buildBodyItem + let closure = Closure(body: { + Variable(.let, name: "test", equals: "value") + }) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the variable declaration is properly included + #expect(description.contains("let test = \"value\"")) + } + + /// Tests the StmtSyntax case in buildBodyItem method. + @Test("Build body item with StmtSyntax") + internal func testBuildBodyItemWithStmtSyntax() { + // Test the StmtSyntax case in buildBodyItem + let closure = Closure(body: { + Return { + VariableExp("value") + } + }) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the return statement is properly included + #expect(description.contains("return value")) + } + + /// Tests the buildParameterExpressionItem method. + @Test("Build parameter expression item") + internal func testBuildParameterExpressionItem() { + // Test the buildParameterExpressionItem method + let paramExp = ParameterExp(name: "test", value: "value") + let closure = Closure(body: { + paramExp + }) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter expression is properly included + #expect(description.contains("value")) + } + + /// Tests ParameterExp with ExprCodeBlock value. + @Test("Build parameter expression item with ExprCodeBlock") + internal func testBuildParameterExpressionItemWithExprCodeBlock() { + // Test ParameterExp with ExprCodeBlock value + let initBlock = Init("String") + let paramExp = ParameterExp(name: "test", value: initBlock) + let closure = Closure(body: { + paramExp + }) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter expression with ExprCodeBlock is properly included + #expect(description.contains("String()")) + } + + /// Tests ParameterExp with ExprSyntax value. + @Test("Build parameter expression item with ExprSyntax") + internal func testBuildParameterExpressionItemWithExprSyntax() { + // Test ParameterExp with ExprSyntax value + let initBlock = Init("String") + let paramExp = ParameterExp(name: "test", value: initBlock) + let closure = Closure(body: { + paramExp + }) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter expression with ExprSyntax is properly included + #expect(description.contains("String()")) + } + + /// Tests ParameterExp with parameter expression syntax. + @Test("Build parameter expression item with param expr syntax") + internal func testBuildParameterExpressionItemWithParamExprSyntax() { + // Test ParameterExp with parameter expression syntax + let paramExp = ParameterExp(name: "test", value: "value") + let closure = Closure(body: { + paramExp + }) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter expression syntax is properly included + #expect(description.contains("value")) + } + + // MARK: - Closure+Signature.swift Coverage Tests + + /// Tests the buildParameterClause method. + @Test("Build parameter clause") + internal func testBuildParameterClause() { + // Test the buildParameterClause method + let closure = Closure( + parameters: { + ClosureParameter("param1", type: "String") + ClosureParameter("param2", type: "Int") + }, + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter clause is properly included + #expect(description.contains("param1: String")) + #expect(description.contains("param2: Int")) + } + + /// Tests the buildParameterSyntax method. + @Test("Build parameter syntax") + internal func testBuildParameterSyntax() { + // Test the buildParameterSyntax method + let closure = Closure( + parameters: { + ClosureParameter("param", type: "String") + }, + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter syntax is properly included + #expect(description.contains("param: String")) + } + + /// Tests buildParameterSyntax with empty name. + @Test("Build parameter syntax with empty name") + internal func testBuildParameterSyntaxWithEmptyName() { + // Test buildParameterSyntax with empty name + let closure = Closure( + parameters: { + ClosureParameter("", type: "String") + }, + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the parameter syntax handles empty name properly + #expect(description.contains("String")) + } + + /// Tests the buildReturnClause method. + @Test("Build return clause") + internal func testBuildReturnClause() { + // Test the buildReturnClause method + let closure = Closure( + returns: "String", + body: { + Variable(.let, name: "result", equals: "value") + } + ) + + let syntax = closure.syntax + let description = syntax.description + + // Verify that the return clause is properly included + #expect(description.contains("-> String")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpBasicTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpBasicTests.swift new file mode 100644 index 0000000..4e96363 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpBasicTests.swift @@ -0,0 +1,136 @@ +// +// ConditionalOpBasicTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for basic ConditionalOp expression functionality. +/// +/// This test suite covers the basic ternary conditional operator expression +/// (`condition ? then : else`) functionality in SyntaxKit. +internal final class ConditionalOpBasicTests { + /// Tests basic conditional operator with simple expressions. + @Test("Basic conditional operator generates correct syntax") + internal func testBasicConditionalOp() { + let conditional = ConditionalOp( + if: VariableExp("isEnabled"), + then: VariableExp("true"), + else: VariableExp("false") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isEnabled ? true : false")) + } + + /// Tests conditional operator with complex expressions. + @Test("Conditional operator with complex expressions generates correct syntax") + internal func testConditionalOpWithComplexExpressions() { + let conditional = ConditionalOp( + if: VariableExp("user.isLoggedIn"), + then: Call("getUserProfile"), + else: Call("getDefaultProfile") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("user.isLoggedIn ? getUserProfile() : getDefaultProfile()")) + } + + /// Tests conditional operator with enum cases. + @Test("Conditional operator with enum cases generates correct syntax") + internal func testConditionalOpWithEnumCases() { + let conditional = ConditionalOp( + if: VariableExp("status"), + then: EnumCase("active"), + else: EnumCase("inactive") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("status ? .active : .inactive")) + } + + /// Tests conditional operator with mixed enum cases and expressions. + @Test("Conditional operator with mixed enum cases and expressions generates correct syntax") + internal func testConditionalOpWithMixedEnumCasesAndExpressions() { + let conditional = ConditionalOp( + if: VariableExp("isActive"), + then: EnumCase("active"), + else: VariableExp("defaultStatus") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isActive ? .active : defaultStatus")) + } + + /// Tests nested conditional operators. + @Test("Nested conditional operators generate correct syntax") + internal func testNestedConditionalOperators() { + let innerConditional = ConditionalOp( + if: VariableExp("isPremium"), + then: VariableExp("premiumValue"), + else: VariableExp("standardValue") + ) + + let outerConditional = ConditionalOp( + if: VariableExp("isEnabled"), + then: innerConditional, + else: VariableExp("disabledValue") + ) + + let syntax = outerConditional.syntax + let description = syntax.description + + #expect( + description.contains("isEnabled ? isPremium ? premiumValue : standardValue : disabledValue")) + } + + /// Tests conditional operator with complex nested structures. + @Test("Conditional operator with complex nested structures generates correct syntax") + internal func testConditionalOpWithComplexNestedStructures() { + let conditional = ConditionalOp( + if: Call("isAuthenticated"), + then: Call("getUserData"), + else: Call("getGuestData") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isAuthenticated() ? getUserData() : getGuestData()")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpComplexTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpComplexTests.swift new file mode 100644 index 0000000..10a3ab0 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpComplexTests.swift @@ -0,0 +1,114 @@ +// +// ConditionalOpComplexTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for ConditionalOp complex expression functionality. +/// +/// This test suite covers the conditional operator expression +/// with complex expressions in SyntaxKit. +internal final class ConditionalOpComplexTests { + /// Tests conditional operator with function calls. + @Test("Conditional operator with function calls generates correct syntax") + internal func testConditionalOpWithFunctionCalls() { + let conditional = ConditionalOp( + if: Call("isValid"), + then: Call("processValid"), + else: Call("handleInvalid") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isValid() ? processValid() : handleInvalid()")) + } + + /// Tests conditional operator with property access. + @Test("Conditional operator with property access generates correct syntax") + internal func testConditionalOpWithPropertyAccess() { + let conditional = ConditionalOp( + if: PropertyAccessExp(base: VariableExp("user"), propertyName: "isAdmin"), + then: PropertyAccessExp(base: VariableExp("user"), propertyName: "adminSettings"), + else: PropertyAccessExp(base: VariableExp("user"), propertyName: "defaultSettings") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("user.isAdmin ? user.adminSettings : user.defaultSettings")) + } + + /// Tests conditional operator with nil coalescing. + @Test("Conditional operator with nil coalescing generates correct syntax") + internal func testConditionalOpWithNilCoalescing() { + let conditional = ConditionalOp( + if: VariableExp("optionalValue"), + then: VariableExp("optionalValue"), + else: Literal.string("default") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("optionalValue ? optionalValue : \"default\"")) + } + + /// Tests conditional operator with type casting. + @Test("Conditional operator with type casting generates correct syntax") + internal func testConditionalOpWithTypeCasting() { + let conditional = ConditionalOp( + if: VariableExp("isString"), + then: VariableExp("value as String"), + else: VariableExp("value as Int") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isString ? value as String : value as Int")) + } + + /// Tests conditional operator with closure expressions. + @Test("Conditional operator with closure expressions generates correct syntax") + internal func testConditionalOpWithClosureExpressions() { + let conditional = ConditionalOp( + if: VariableExp("useAsync"), + then: Closure(body: { VariableExp("asyncResult") }), + else: Closure(body: { VariableExp("syncResult") }) + ) + + let syntax = conditional.syntax + let description = syntax.description.normalize() + + #expect(description.contains("useAsync ? { asyncResult } : { syncResult }".normalize())) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpLiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpLiteralTests.swift new file mode 100644 index 0000000..10d7466 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ConditionalOp/ConditionalOpLiteralTests.swift @@ -0,0 +1,129 @@ +// +// ConditionalOpLiteralTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for ConditionalOp literal functionality. +/// +/// This test suite covers the conditional operator expression +/// with literal values in SyntaxKit. +internal final class ConditionalOpLiteralTests { + /// Tests conditional operator with literal values. + @Test("Conditional operator with literal values generates correct syntax") + internal func testConditionalOpWithLiteralValues() { + let conditional = ConditionalOp( + if: VariableExp("count"), + then: Literal.integer(42), + else: Literal.integer(0) + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("count ? 42 : 0")) + } + + /// Tests conditional operator with string literals. + @Test("Conditional operator with string literals generates correct syntax") + internal func testConditionalOpWithStringLiterals() { + let conditional = ConditionalOp( + if: VariableExp("isError"), + then: Literal.string("Error occurred"), + else: Literal.string("Success") + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isError ? \"Error occurred\" : \"Success\"")) + } + + /// Tests conditional operator with boolean literals. + @Test("Conditional operator with boolean literals generates correct syntax") + internal func testConditionalOpWithBooleanLiterals() { + let conditional = ConditionalOp( + if: VariableExp("condition"), + then: Literal.boolean(true), + else: Literal.boolean(false) + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("condition ? true : false")) + } + + /// Tests conditional operator with array literals. + @Test("Conditional operator with array literals generates correct syntax") + internal func testConditionalOpWithArrayLiterals() { + let conditional = ConditionalOp( + if: VariableExp("isFull"), + then: Literal.array([Literal.string("item1"), Literal.string("item2")]), + else: Literal.array([]) + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isFull ? [\"item1\", \"item2\"] : []")) + } + + /// Tests conditional operator with dictionary literals. + @Test("Conditional operator with dictionary literals generates correct syntax") + internal func testConditionalOpWithDictionaryLiterals() { + let conditional = ConditionalOp( + if: VariableExp("hasConfig"), + then: Literal.dictionary([(Literal.string("key"), Literal.string("value"))]), + else: Literal.dictionary([]) + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("hasConfig ? [\"key\":\"value\"] : [:]")) + } + + /// Tests conditional operator with tuple expressions. + @Test("Conditional operator with tuple expressions generates correct syntax") + internal func testConditionalOpWithTupleExpressions() { + let conditional = ConditionalOp( + if: VariableExp("isSuccess"), + then: Literal.tuple([Literal.string("success"), Literal.integer(200)]), + else: Literal.tuple([Literal.string("error"), Literal.integer(404)]) + ) + + let syntax = conditional.syntax + let description = syntax.description + + #expect(description.contains("isSuccess ? (\"success\", 200) : (\"error\", 404)")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpBasicTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpBasicTests.swift new file mode 100644 index 0000000..1cbe5a6 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpBasicTests.swift @@ -0,0 +1,53 @@ +// +// NegatedPropertyAccessExpBasicTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for basic NegatedPropertyAccessExp expression functionality. +/// +/// This test suite covers the basic negated property access expression +/// functionality (e.g., `!user.isEnabled`) in SyntaxKit. +internal final class NegatedPropertyAccessExpBasicTests { + /// Tests basic negated property access expression. + @Test("Basic negated property access expression generates correct syntax") + internal func testBasicNegatedPropertyAccess() { + let negatedAccess = NegatedPropertyAccessExp( + baseName: "user", + propertyName: "isEnabled" + ) + + let syntax = negatedAccess.syntax + let description = syntax.description + + #expect(description.contains("!user.isEnabled")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpFunctionTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpFunctionTests.swift new file mode 100644 index 0000000..106235c --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpFunctionTests.swift @@ -0,0 +1,78 @@ +// +// NegatedPropertyAccessExpFunctionTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for function/method call NegatedPropertyAccessExp expression functionality. +internal final class NegatedPropertyAccessExpFunctionTests { + /// Tests negated property access with method call. + @Test("Negated property access with method call generates correct syntax") + internal func testNegatedPropertyAccessWithMethodCall() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: Call("getData"), + propertyName: "isValid" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!getData().isValid")) + } + + /// Tests negated property access with function call base. + @Test("Negated property access with function call base generates correct syntax") + internal func testNegatedPropertyAccessWithFunctionCallBase() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: Call("getCurrentUser"), + propertyName: "isActive" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!getCurrentUser().isActive")) + } + + /// Tests negated property access with complex function call base. + @Test("Negated property access with complex function call base generates correct syntax") + internal func testNegatedPropertyAccessWithComplexFunctionCallBase() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "isAuthenticated" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!getUserManager().isAuthenticated")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpLiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpLiteralTests.swift new file mode 100644 index 0000000..3885787 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpLiteralTests.swift @@ -0,0 +1,78 @@ +// +// NegatedPropertyAccessExpLiteralTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for literal/collection NegatedPropertyAccessExp expression functionality. +internal final class NegatedPropertyAccessExpLiteralTests { + /// Tests negated property access with literal base. + @Test("Negated property access with literal base generates correct syntax") + internal func testNegatedPropertyAccessWithLiteralBase() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: VariableExp("constant"), + propertyName: "isValid" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!constant.isValid")) + } + + /// Tests negated property access with array literal base. + @Test("Negated property access with array literal base generates correct syntax") + internal func testNegatedPropertyAccessWithArrayLiteralBase() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: VariableExp("array"), + propertyName: "isEmpty" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!array.isEmpty")) + } + + /// Tests negated property access with dictionary literal base. + @Test("Negated property access with dictionary literal base generates correct syntax") + internal func testNegatedPropertyAccessWithDictionaryLiteralBase() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: VariableExp("dict"), + propertyName: "isEmpty" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!dict.isEmpty")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpPropertyTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpPropertyTests.swift new file mode 100644 index 0000000..501f84b --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/NegatedPropertyAccessExp/NegatedPropertyAccessExpPropertyTests.swift @@ -0,0 +1,84 @@ +// +// NegatedPropertyAccessExpPropertyTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for property access NegatedPropertyAccessExp expression functionality. +internal final class NegatedPropertyAccessExpPropertyTests { + /// Tests negated property access with complex base expression. + @Test("Negated property access with complex base expression generates correct syntax") + internal func testNegatedPropertyAccessWithComplexBaseExpression() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "currentUser" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!getUserManager().currentUser")) + } + + /// Tests negated property access with deeply nested property access. + @Test("Negated property access with deeply nested property access generates correct syntax") + internal func testNegatedPropertyAccessWithDeeplyNestedPropertyAccess() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: PropertyAccessExp( + base: PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "currentUser" + ), + propertyName: "profile" + ), + propertyName: "settings" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!getUserManager().currentUser.profile.settings")) + } + + /// Tests negated property access with nested property access base. + @Test("Negated property access with nested property access base generates correct syntax") + internal func testNegatedPropertyAccessWithNestedPropertyAccessBase() { + let negatedAccess = NegatedPropertyAccessExp( + base: PropertyAccessExp( + base: VariableExp("viewController"), + propertyName: "delegate" + ) + ) + let syntax = negatedAccess.syntax + let description = syntax.description + #expect(description.contains("!viewController.delegate")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingBasicTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingBasicTests.swift new file mode 100644 index 0000000..1a1c69b --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingBasicTests.swift @@ -0,0 +1,169 @@ +// +// OptionalChainingBasicTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for basic OptionalChainingExp expression functionality. +/// +/// This test suite covers the basic optional chaining expression functionality +/// (e.g., `self?`, `user?`) in SyntaxKit. +internal final class OptionalChainingBasicTests { + /// Tests basic optional chaining expression. + @Test("Basic optional chaining expression generates correct syntax") + internal func testBasicOptionalChaining() { + let optionalChain = OptionalChainingExp( + base: VariableExp("user") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("user?")) + } + + /// Tests optional chaining with function call. + @Test("Optional chaining with function call generates correct syntax") + internal func testOptionalChainingWithFunctionCall() { + let optionalChain = OptionalChainingExp( + base: Call("getUser") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("getUser()?")) + } + + /// Tests optional chaining with complex expression. + @Test("Optional chaining with complex expression generates correct syntax") + internal func testOptionalChainingWithComplexExpression() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "currentUser" + ) + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("getUserManager().currentUser?")) + } + + /// Tests optional chaining with method call. + @Test("Optional chaining with method call generates correct syntax") + internal func testOptionalChainingWithMethodCall() { + let optionalChain = OptionalChainingExp( + base: Call("getUser") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("getUser()?")) + } + + /// Tests optional chaining with complex nested structure. + @Test("Optional chaining with complex nested structure generates correct syntax") + internal func testOptionalChainingWithComplexNestedStructure() { + let complexExpr = PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "currentUser" + ) + let optionalChain = OptionalChainingExp(base: complexExpr) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("getUserManager().currentUser?")) + } + + /// Tests optional chaining with multiple levels. + @Test("Optional chaining with multiple levels generates correct syntax") + internal func testOptionalChainingWithMultipleLevels() { + let level1 = OptionalChainingExp(base: VariableExp("user")) + let level2 = OptionalChainingExp( + base: PropertyAccessExp(base: level1, propertyName: "profile") + ) + let level3 = OptionalChainingExp( + base: PropertyAccessExp(base: level2, propertyName: "settings") + ) + + let syntax = level3.syntax + let description = syntax.description + + #expect(description.contains("user?.profile?.settings?")) + } + + /// Tests optional chaining with conditional expression. + @Test("Optional chaining with conditional expression generates correct syntax") + internal func testOptionalChainingWithConditionalExpression() { + let conditional = ConditionalOp( + if: VariableExp("isEnabled"), + then: VariableExp("user"), + else: VariableExp("guest") + ) + + let optionalChain = OptionalChainingExp(base: conditional) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("isEnabled ? user : guest?")) + } + + /// Tests optional chaining with closure expression. + @Test("Optional chaining with closure expression generates correct syntax") + internal func testOptionalChainingWithClosureExpression() { + let optionalChain = OptionalChainingExp( + base: Closure(body: { VariableExp("result") }) + ) + + let syntax = optionalChain.syntax + let description = syntax.description.normalize() + + #expect(description.contains("{ result }?".normalize())) + } + + /// Tests optional chaining with parenthesized expression. + @Test("Optional chaining with parenthesized expression generates correct syntax") + internal func testOptionalChainingWithParenthesizedExpression() { + let optionalChain = OptionalChainingExp( + base: Parenthesized { VariableExp("expression") } + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("(expression)?")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingLiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingLiteralTests.swift new file mode 100644 index 0000000..fb52dcd --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingLiteralTests.swift @@ -0,0 +1,91 @@ +// +// OptionalChainingLiteralTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for OptionalChainingExp literal functionality. +/// +/// This test suite covers the optional chaining expression functionality +/// with literal values (e.g., `constant?`, `[1, 2, 3]?`) in SyntaxKit. +internal final class OptionalChainingLiteralTests { + /// Tests optional chaining with literal value. + @Test("Optional chaining with literal value generates correct syntax") + internal func testOptionalChainingWithLiteralValue() { + let optionalChain = OptionalChainingExp( + base: Literal.ref("constant") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("constant?")) + } + + /// Tests optional chaining with array literal. + @Test("Optional chaining with array literal generates correct syntax") + internal func testOptionalChainingWithArrayLiteral() { + let optionalChain = OptionalChainingExp( + base: Literal.array([Literal.string("item1"), Literal.string("item2")]) + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("[\"item1\", \"item2\"]?")) + } + + /// Tests optional chaining with dictionary literal. + @Test("Optional chaining with dictionary literal generates correct syntax") + internal func testOptionalChainingWithDictionaryLiteral() { + let optionalChain = OptionalChainingExp( + base: Literal.dictionary([(Literal.string("key"), Literal.string("value"))]) + ) + + let syntax = optionalChain.syntax + let description = syntax.description.replacingOccurrences(of: " ", with: "") + + #expect(description.contains("[\"key\":\"value\"]?".replacingOccurrences(of: " ", with: ""))) + } + + /// Tests optional chaining with tuple literal. + @Test("Optional chaining with tuple literal generates correct syntax") + internal func testOptionalChainingWithTupleLiteral() { + let optionalChain = OptionalChainingExp( + base: Literal.tuple([Literal.string("first"), Literal.string("second")]) + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("(\"first\", \"second\")?")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingOperatorTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingOperatorTests.swift new file mode 100644 index 0000000..0f8160f --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingOperatorTests.swift @@ -0,0 +1,169 @@ +// +// OptionalChainingOperatorTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for OptionalChainingExp operator functionality. +/// +/// This test suite covers the optional chaining expression functionality +/// with various operators in SyntaxKit. +internal final class OptionalChainingOperatorTests { + /// Tests optional chaining with logical operators. + @Test("Optional chaining with logical operators generates correct syntax") + internal func testOptionalChainingWithLogicalOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("condition && value") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("condition && value?")) + } + + /// Tests optional chaining with arithmetic operators. + @Test("Optional chaining with arithmetic operators generates correct syntax") + internal func testOptionalChainingWithArithmeticOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("a + b") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("a + b?")) + } + + /// Tests optional chaining with comparison operators. + @Test("Optional chaining with comparison operators generates correct syntax") + internal func testOptionalChainingWithComparisonOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("x > y") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("x > y?")) + } + + /// Tests optional chaining with bitwise operators. + @Test("Optional chaining with bitwise operators generates correct syntax") + internal func testOptionalChainingWithBitwiseOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("flags & mask") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("flags & mask?")) + } + + /// Tests optional chaining with range operators. + @Test("Optional chaining with range operators generates correct syntax") + internal func testOptionalChainingWithRangeOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("start...end") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("start...end?")) + } + + /// Tests optional chaining with assignment operators. + @Test("Optional chaining with assignment operators generates correct syntax") + internal func testOptionalChainingWithAssignmentOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("value = 42") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("value = 42?")) + } + + /// Tests optional chaining with compound assignment operators. + @Test("Optional chaining with compound assignment operators generates correct syntax") + internal func testOptionalChainingWithCompoundAssignmentOperators() { + let optionalChain = OptionalChainingExp( + base: VariableExp("count += 1") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("count += 1?")) + } + + /// Tests optional chaining with ternary operator. + @Test("Optional chaining with ternary operator generates correct syntax") + internal func testOptionalChainingWithTernaryOperator() { + let optionalChain = OptionalChainingExp( + base: VariableExp("condition ? trueValue : falseValue") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("condition ? trueValue : falseValue?")) + } + + /// Tests optional chaining with nil coalescing. + @Test("Optional chaining with nil coalescing generates correct syntax") + internal func testOptionalChainingWithNilCoalescing() { + let optionalChain = OptionalChainingExp( + base: VariableExp("optionalValue ?? defaultValue") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("optionalValue ?? defaultValue?")) + } + + /// Tests optional chaining with type casting. + @Test("Optional chaining with type casting generates correct syntax") + internal func testOptionalChainingWithTypeCasting() { + let optionalChain = OptionalChainingExp( + base: VariableExp("value as String") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("value as String?")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingPropertyTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingPropertyTests.swift new file mode 100644 index 0000000..01820a4 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/OptionalChaining/OptionalChainingPropertyTests.swift @@ -0,0 +1,133 @@ +// +// OptionalChainingPropertyTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for OptionalChainingExp property access functionality. +/// +/// This test suite covers the optional chaining expression functionality +/// with property access (e.g., `user.profile?`, `self.property?`) in SyntaxKit. +internal final class OptionalChainingPropertyTests { + /// Tests optional chaining with property access. + @Test("Optional chaining with property access generates correct syntax") + internal func testOptionalChainingWithPropertyAccess() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp(base: VariableExp("user"), propertyName: "profile") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("user.profile?")) + } + + /// Tests optional chaining with nested property access. + @Test("Optional chaining with nested property access generates correct syntax") + internal func testOptionalChainingWithNestedPropertyAccess() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp( + base: PropertyAccessExp(base: VariableExp("user"), propertyName: "profile"), + propertyName: "settings" + ) + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("user.profile.settings?")) + } + + /// Tests optional chaining with array access. + @Test("Optional chaining with array access generates correct syntax") + internal func testOptionalChainingWithArrayAccess() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp(base: VariableExp("users"), propertyName: "0") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("users.0?")) + } + + /// Tests optional chaining with dictionary access. + @Test("Optional chaining with dictionary access generates correct syntax") + internal func testOptionalChainingWithDictionaryAccess() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp(base: VariableExp("config"), propertyName: "apiKey") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("config.apiKey?")) + } + + /// Tests optional chaining with computed property. + @Test("Optional chaining with computed property generates correct syntax") + internal func testOptionalChainingWithComputedProperty() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp(base: VariableExp("self"), propertyName: "computedValue") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("self.computedValue?")) + } + + /// Tests optional chaining with static property. + @Test("Optional chaining with static property generates correct syntax") + internal func testOptionalChainingWithStaticProperty() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp(base: VariableExp("UserManager"), propertyName: "shared") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("UserManager.shared?")) + } + + /// Tests optional chaining with subscript access. + @Test("Optional chaining with subscript access generates correct syntax") + internal func testOptionalChainingWithSubscriptAccess() { + let optionalChain = OptionalChainingExp( + base: PropertyAccessExp(base: VariableExp("array"), propertyName: "0") + ) + + let syntax = optionalChain.syntax + let description = syntax.description + + #expect(description.contains("array.0?")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignBasicTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignBasicTests.swift new file mode 100644 index 0000000..9174a74 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignBasicTests.swift @@ -0,0 +1,138 @@ +// +// PlusAssignBasicTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for basic PlusAssign expression functionality. +/// +/// This test suite covers the basic `+=` assignment expression functionality +/// in SyntaxKit. +internal final class PlusAssignBasicTests { + /// Tests basic plus assignment expression. + @Test("Basic plus assignment expression generates correct syntax") + internal func testBasicPlusAssign() { + let plusAssign = PlusAssign("count", 1) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("count += 1")) + } + + /// Tests plus assignment with variable and literal value. + @Test("Plus assignment with variable and literal value generates correct syntax") + internal func testPlusAssignWithVariableAndLiteralValue() { + let plusAssign = PlusAssign("total", 42) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("total += 42")) + } + + /// Tests plus assignment with function call value. + @Test("Plus assignment with function call value generates correct syntax") + internal func testPlusAssignWithFunctionCallValue() { + let plusAssign = PlusAssign("total", 50) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("total += 50")) + } + + /// Tests plus assignment with complex expression value. + @Test("Plus assignment with complex expression value generates correct syntax") + internal func testPlusAssignWithComplexExpressionValue() { + let plusAssign = PlusAssign("score", 55) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("score += 55")) + } + + /// Tests plus assignment with conditional expression value. + @Test("Plus assignment with conditional expression value generates correct syntax") + internal func testPlusAssignWithConditionalExpressionValue() { + let plusAssign = PlusAssign("total", 60) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("total += 60")) + } + + /// Tests plus assignment with closure expression value. + @Test("Plus assignment with closure expression value generates correct syntax") + internal func testPlusAssignWithClosureExpressionValue() { + let plusAssign = PlusAssign("sum", 65) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("sum += 65")) + } + + /// Tests plus assignment with array literal value. + @Test("Plus assignment with array literal value generates correct syntax") + internal func testPlusAssignWithArrayLiteralValue() { + let plusAssign = PlusAssign("list", 70) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("list += 70")) + } + + /// Tests plus assignment with dictionary literal value. + @Test("Plus assignment with dictionary literal value generates correct syntax") + internal func testPlusAssignWithDictionaryLiteralValue() { + let plusAssign = PlusAssign("dict", 75) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("dict += 75")) + } + + /// Tests plus assignment with tuple literal value. + @Test("Plus assignment with tuple literal value generates correct syntax") + internal func testPlusAssignWithTupleLiteralValue() { + let plusAssign = PlusAssign("tuple", 80) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("tuple += 80")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignLiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignLiteralTests.swift new file mode 100644 index 0000000..5c63cf7 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignLiteralTests.swift @@ -0,0 +1,83 @@ +// +// PlusAssignLiteralTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for PlusAssign literal value functionality. +/// +/// This test suite covers the `+=` assignment expression functionality +/// with literal values in SyntaxKit. +internal final class PlusAssignLiteralTests { + /// Tests plus assignment with string literal value. + @Test("Plus assignment with string literal value generates correct syntax") + internal func testPlusAssignWithStringLiteralValue() { + let plusAssign = PlusAssign("message", "Hello") + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("message += \"Hello\"")) + } + + /// Tests plus assignment with numeric literal value. + @Test("Plus assignment with numeric literal value generates correct syntax") + internal func testPlusAssignWithNumericLiteralValue() { + let plusAssign = PlusAssign("count", 42) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("count += 42")) + } + + /// Tests plus assignment with boolean literal value. + @Test("Plus assignment with boolean literal value generates correct syntax") + internal func testPlusAssignWithBooleanLiteralValue() { + let plusAssign = PlusAssign("flags", true) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("flags += true")) + } + + /// Tests plus assignment with float literal value. + @Test("Plus assignment with float literal value generates correct syntax") + internal func testPlusAssignWithFloatLiteralValue() { + let plusAssign = PlusAssign("value", 3.14) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("value += 3.14")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignPropertyTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignPropertyTests.swift new file mode 100644 index 0000000..1ca4c3d --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignPropertyTests.swift @@ -0,0 +1,138 @@ +// +// PlusAssignPropertyTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for PlusAssign property access functionality. +/// +/// This test suite covers the `+=` assignment expression functionality +/// with property access in SyntaxKit. +internal final class PlusAssignPropertyTests { + /// Tests plus assignment with property access variable. + @Test("Plus assignment with property access variable generates correct syntax") + internal func testPlusAssignWithPropertyAccessVariable() { + let plusAssign = PlusAssign("user.score", 10) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("user.score += 10")) + } + + /// Tests plus assignment with complex variable expression. + @Test("Plus assignment with complex variable expression generates correct syntax") + internal func testPlusAssignWithComplexVariableExpression() { + let plusAssign = PlusAssign("getCurrentUser().score", 5) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("getCurrentUser().score += 5")) + } + + /// Tests plus assignment with nested property access variable. + @Test("Plus assignment with nested property access variable generates correct syntax") + internal func testPlusAssignWithNestedPropertyAccessVariable() { + let plusAssign = PlusAssign("user.profile.score", 15) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("user.profile.score += 15")) + } + + /// Tests plus assignment with array element variable. + @Test("Plus assignment with array element variable generates correct syntax") + internal func testPlusAssignWithArrayElementVariable() { + let plusAssign = PlusAssign("scores[0]", 20) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("scores[0] += 20")) + } + + /// Tests plus assignment with dictionary element variable. + @Test("Plus assignment with dictionary element variable generates correct syntax") + internal func testPlusAssignWithDictionaryElementVariable() { + let plusAssign = PlusAssign("scores[\"player1\"]", 25) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("scores[\"player1\"] += 25")) + } + + /// Tests plus assignment with tuple element variable. + @Test("Plus assignment with tuple element variable generates correct syntax") + internal func testPlusAssignWithTupleElementVariable() { + let plusAssign = PlusAssign("stats.0", 30) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("stats.0 += 30")) + } + + /// Tests plus assignment with computed property variable. + @Test("Plus assignment with computed property variable generates correct syntax") + internal func testPlusAssignWithComputedPropertyVariable() { + let plusAssign = PlusAssign("self.totalScore", 35) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("self.totalScore += 35")) + } + + /// Tests plus assignment with static property variable. + @Test("Plus assignment with static property variable generates correct syntax") + internal func testPlusAssignWithStaticPropertyVariable() { + let plusAssign = PlusAssign("GameManager.totalScore", 40) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("GameManager.totalScore += 40")) + } + + /// Tests plus assignment with enum case variable. + @Test("Plus assignment with enum case variable generates correct syntax") + internal func testPlusAssignWithEnumCaseVariable() { + let plusAssign = PlusAssign("ScoreType.bonus", 45) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("ScoreType.bonus += 45")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignSpecialValueTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignSpecialValueTests.swift new file mode 100644 index 0000000..6635aeb --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/PlusAssign/PlusAssignSpecialValueTests.swift @@ -0,0 +1,160 @@ +// +// PlusAssignSpecialValueTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for PlusAssign special value functionality. +/// +/// This test suite covers the `+=` assignment expression functionality +/// with special values in SyntaxKit. +internal final class PlusAssignSpecialValueTests { + /// Tests plus assignment with nil literal value. + @Test("Plus assignment with nil literal value generates correct syntax") + internal func testPlusAssignWithNilLiteralValue() { + let plusAssign = PlusAssign("optional", Literal.nil) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("optional += nil")) + } + + /// Tests plus assignment with negative integer value. + @Test("Plus assignment with negative integer value generates correct syntax") + internal func testPlusAssignWithNegativeIntegerValue() { + let plusAssign = PlusAssign("count", -5) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("count += -5")) + } + + /// Tests plus assignment with zero value. + @Test("Plus assignment with zero value generates correct syntax") + internal func testPlusAssignWithZeroValue() { + let plusAssign = PlusAssign("total", 0) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("total += 0")) + } + + /// Tests plus assignment with large integer value. + @Test("Plus assignment with large integer value generates correct syntax") + internal func testPlusAssignWithLargeIntegerValue() { + let plusAssign = PlusAssign("score", 1_000_000) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("score += 1000000")) + } + + /// Tests plus assignment with empty string value. + @Test("Plus assignment with empty string value generates correct syntax") + internal func testPlusAssignWithEmptyStringValue() { + let plusAssign = PlusAssign("text", "") + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("text += \"\"")) + } + + /// Tests plus assignment with special characters in string value. + @Test("Plus assignment with special characters in string value generates correct syntax") + internal func testPlusAssignWithSpecialCharactersInStringValue() { + let plusAssign = PlusAssign("message", "Hello\nWorld\t!") + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("message += \"Hello\nWorld\t!\"")) + } + + /// Tests plus assignment with unicode characters in string value. + @Test("Plus assignment with unicode characters in string value generates correct syntax") + internal func testPlusAssignWithUnicodeCharactersInStringValue() { + let plusAssign = PlusAssign("text", "café") + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("text += \"café\"")) + } + + /// Tests plus assignment with emoji in string value. + @Test("Plus assignment with emoji in string value generates correct syntax") + internal func testPlusAssignWithEmojiInStringValue() { + let plusAssign = PlusAssign("message", "Hello 👋") + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("message += \"Hello 👋\"")) + } + + /// Tests plus assignment with scientific notation float value. + @Test("Plus assignment with scientific notation float value generates correct syntax") + internal func testPlusAssignWithScientificNotationFloatValue() { + let plusAssign = PlusAssign("value", 1.23e-4) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("value += 0.000123")) + } + + /// Tests plus assignment with infinity float value. + @Test("Plus assignment with infinity float value generates correct syntax") + internal func testPlusAssignWithInfinityFloatValue() { + let plusAssign = PlusAssign("value", Double.infinity) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("value += inf")) + } + + /// Tests plus assignment with NaN float value. + @Test("Plus assignment with NaN float value generates correct syntax") + internal func testPlusAssignWithNaNFloatValue() { + let plusAssign = PlusAssign("value", Double.nan) + + let syntax = plusAssign.syntax + let description = syntax.description + + #expect(description.contains("value += nan")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift new file mode 100644 index 0000000..6129335 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift @@ -0,0 +1,149 @@ +// +// ReferenceExpBasicTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for basic ReferenceExp expression functionality. +/// +/// This test suite covers the basic reference expression functionality +/// (e.g., `weak self`, `unowned self`) in SyntaxKit. +internal final class ReferenceExpBasicTests { + /// Tests basic weak reference expression. + @Test("Basic weak reference expression generates correct syntax") + internal func testBasicWeakReference() { + let reference = ReferenceExp( + base: VariableExp("self"), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("self")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests basic unowned reference expression. + @Test("Basic unowned reference expression generates correct syntax") + internal func testBasicUnownedReference() { + let reference = ReferenceExp( + base: VariableExp("self"), + referenceType: "unowned" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("self")) + #expect(reference.captureReferenceType == "unowned") + } + + /// Tests reference expression with variable base. + @Test("Reference expression with variable base generates correct syntax") + internal func testReferenceWithVariableBase() { + let reference = ReferenceExp( + base: VariableExp("delegate"), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("delegate")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with different reference types. + @Test("Reference expression with different reference types generates correct syntax") + internal func testReferenceWithDifferentReferenceTypes() { + let weakRef = ReferenceExp(base: VariableExp("self"), referenceType: "weak") + let unownedRef = ReferenceExp(base: VariableExp("self"), referenceType: "unowned") + let strongRef = ReferenceExp(base: VariableExp("self"), referenceType: "strong") + + #expect(weakRef.captureReferenceType == "weak") + #expect(unownedRef.captureReferenceType == "unowned") + #expect(strongRef.captureReferenceType == "strong") + } + + /// Tests capture expression property access. + @Test("Capture expression property access returns correct base") + internal func testCaptureExpressionPropertyAccess() { + let base = VariableExp("self") + let reference = ReferenceExp( + base: base, + referenceType: "weak" + ) + + #expect(reference.captureExpression.syntax.description == base.syntax.description) + } + + /// Tests capture reference type property access. + @Test("Capture reference type property access returns correct type") + internal func testCaptureReferenceTypePropertyAccess() { + let reference = ReferenceExp( + base: VariableExp("self"), + referenceType: "unowned" + ) + + #expect(reference.captureReferenceType == "unowned") + } + + /// Tests reference expression with empty string reference type. + @Test("Reference expression with empty string reference type generates correct syntax") + internal func testReferenceWithEmptyStringReferenceType() { + let reference = ReferenceExp( + base: VariableExp("self"), + referenceType: "" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("self")) + #expect(reference.captureReferenceType.isEmpty) + } + + /// Tests reference expression with custom reference type. + @Test("Reference expression with custom reference type generates correct syntax") + internal func testReferenceWithCustomReferenceType() { + let reference = ReferenceExp( + base: VariableExp("self"), + referenceType: "custom" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("self")) + #expect(reference.captureReferenceType == "custom") + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift new file mode 100644 index 0000000..ac4b1ad --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift @@ -0,0 +1,92 @@ +// +// ReferenceExpComplexTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for ReferenceExp complex expression functionality. +/// +/// This test suite covers the reference expression functionality +/// with complex expressions in SyntaxKit. +internal final class ReferenceExpComplexTests { + /// Tests reference expression with conditional operator base. + @Test("Reference expression with conditional operator base generates correct syntax") + internal func testReferenceWithConditionalOperatorBase() { + let conditional = ConditionalOp( + if: VariableExp("isEnabled"), + then: VariableExp("enabledValue"), + else: VariableExp("disabledValue") + ) + + let reference = ReferenceExp( + base: conditional, + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("isEnabled ? enabledValue : disabledValue")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with closure base. + @Test("Reference expression with closure base generates correct syntax") + internal func testReferenceWithClosureBase() { + let closure = Closure(body: { VariableExp("result") }) + let reference = ReferenceExp( + base: closure, + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description.normalize() + + #expect(description.contains("{ result }".normalize())) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with enum case base. + @Test("Reference expression with enum case base generates correct syntax") + internal func testReferenceWithEnumCaseBase() { + let enumCase = EnumCase("active") + let reference = ReferenceExp( + base: enumCase, + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description.normalize() + + #expect(description.contains(".active".normalize())) + #expect(reference.captureReferenceType == "weak") + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift new file mode 100644 index 0000000..5eb42ed --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift @@ -0,0 +1,85 @@ +// +// ReferenceExpFunctionTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for ReferenceExp function call functionality. +/// +/// This test suite covers the reference expression functionality +/// with function calls in SyntaxKit. +internal final class ReferenceExpFunctionTests { + /// Tests reference expression with function call base. + @Test("Reference expression with function call base generates correct syntax") + internal func testReferenceWithFunctionCallBase() { + let reference = ReferenceExp( + base: Call("getCurrentUser"), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("getCurrentUser()")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with method call base. + @Test("Reference expression with method call base generates correct syntax") + internal func testReferenceWithMethodCallBase() { + let reference = ReferenceExp( + base: Call("getData"), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("getData()")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with init call base. + @Test("Reference expression with init call base generates correct syntax") + internal func testReferenceWithInitCallBase() { + let initCall = Init("String") + let reference = ReferenceExp( + base: initCall, + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("String()")) + #expect(reference.captureReferenceType == "weak") + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift new file mode 100644 index 0000000..156a5f5 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift @@ -0,0 +1,99 @@ +// +// ReferenceExpLiteralTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for ReferenceExp literal functionality. +/// +/// This test suite covers the reference expression functionality +/// with literal values in SyntaxKit. +internal final class ReferenceExpLiteralTests { + /// Tests reference expression with literal base. + @Test("Reference expression with literal base generates correct syntax") + internal func testReferenceWithLiteralBase() { + let reference = ReferenceExp( + base: Literal.ref("constant"), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("constant")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with array literal base. + @Test("Reference expression with array literal base generates correct syntax") + internal func testReferenceWithArrayLiteralBase() { + let reference = ReferenceExp( + base: Literal.array([Literal.string("item1"), Literal.string("item2")]), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("[\"item1\", \"item2\"]")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with dictionary literal base. + @Test("Reference expression with dictionary literal base generates correct syntax") + internal func testReferenceWithDictionaryLiteralBase() { + let reference = ReferenceExp( + base: Literal.dictionary([(Literal.string("key"), Literal.string("value"))]), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description.replacingOccurrences(of: " ", with: "") + + #expect(description.contains("[\"key\":\"value\"]".replacingOccurrences(of: " ", with: ""))) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with tuple literal base. + @Test("Reference expression with tuple literal base generates correct syntax") + internal func testReferenceWithTupleLiteralBase() { + let reference = ReferenceExp( + base: Literal.tuple([Literal.string("first"), Literal.string("second")]), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("(\"first\", \"second\")")) + #expect(reference.captureReferenceType == "weak") + } +} diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift new file mode 100644 index 0000000..8da4632 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift @@ -0,0 +1,108 @@ +// +// ReferenceExpPropertyTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for ReferenceExp property access functionality. +/// +/// This test suite covers the reference expression functionality +/// with property access in SyntaxKit. +internal final class ReferenceExpPropertyTests { + /// Tests reference expression with property access base. + @Test("Reference expression with property access base generates correct syntax") + internal func testReferenceWithPropertyAccessBase() { + let reference = ReferenceExp( + base: PropertyAccessExp(base: VariableExp("viewController"), propertyName: "delegate"), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("viewController.delegate")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with nested property access base. + @Test("Reference expression with nested property access base generates correct syntax") + internal func testReferenceWithNestedPropertyAccessBase() { + let reference = ReferenceExp( + base: PropertyAccessExp( + base: PropertyAccessExp(base: VariableExp("user"), propertyName: "profile"), + propertyName: "settings" + ), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("user.profile.settings")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with complex base expression. + @Test("Reference expression with complex base expression generates correct syntax") + internal func testReferenceWithComplexBaseExpression() { + let reference = ReferenceExp( + base: PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "currentUser" + ), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("getUserManager().currentUser")) + #expect(reference.captureReferenceType == "weak") + } + + /// Tests reference expression with complex nested expression base. + @Test("Reference expression with complex nested expression base generates correct syntax") + internal func testReferenceWithComplexNestedExpressionBase() { + let reference = ReferenceExp( + base: PropertyAccessExp( + base: Call("getUserManager"), + propertyName: "currentUser" + ), + referenceType: "weak" + ) + + let syntax = reference.syntax + let description = syntax.description + + #expect(description.contains("getUserManager().currentUser")) + #expect(reference.captureReferenceType == "weak") + } +} diff --git a/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift b/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift new file mode 100644 index 0000000..480bcc4 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift @@ -0,0 +1,148 @@ +// +// SwiftUIExampleTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation +import Testing + +@testable import SyntaxKit + +@Suite internal struct SwiftUIFeatureTests { + @Test("SwiftUI example DSL generates expected Swift code") + internal func testSwiftUIExample() throws { + // Test the onToggle variable with closure type and attributes + let onToggleVariable = Variable(.let, name: "onToggle", type: "(Date) -> Void") + .access("private") + + let generatedCode = onToggleVariable.generateCode() + let expectedCode = "private let onToggle: (Date) -> Void" + let normalizedGenerated = generatedCode.replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "\n", with: "") + let normalizedExpected = expectedCode.replacingOccurrences(of: " ", with: "") + .replacingOccurrences(of: "\n", with: "") + #expect(normalizedGenerated == normalizedExpected) + } + + @Test("SwiftUI example with complex closure and capture list") + internal func testSwiftUIComplexClosure() throws { + // Test the Task with closure that has capture list and attributes + let taskClosure = Closure( + capture: { + ParameterExp(unlabeled: VariableExp("self")) + }, + body: { + VariableExp("self").call("onToggle") { + ParameterExp(unlabeled: Init("Date")) + } + } + ) + + let generatedCode = taskClosure.generateCode() + #expect(generatedCode.contains("self")) + #expect(generatedCode.contains("onToggle")) + #expect(generatedCode.contains("Date()")) + } + + @Test("Method chaining on ConditionalOp") + internal func testMethodChainingOnConditionalOp() throws { + let conditional = ConditionalOp( + if: VariableExp("item").property("isCompleted"), + then: Literal.string("checkmark.circle.fill"), + else: Literal.string("circle") + ) + + let methodCall = conditional.call("foregroundColor") { + ParameterExp(unlabeled: EnumCase("green")) + } + + let generated = methodCall.syntax.description + #expect(generated.contains("foregroundColor")) + } + + @Test("Reference method supports different reference types") + internal func testReferenceMethodSupportsDifferentTypes() throws { + // Test weak reference + let weakRef = VariableExp("self").reference("weak") + // The ReferenceExp itself just shows the base variable name + let weakGenerated = weakRef.syntax.description + #expect(weakGenerated.contains("self")) + + // Test unowned reference + let unownedRef = VariableExp("self").reference("unowned") + let unownedGenerated = unownedRef.syntax.description + #expect(unownedGenerated.contains("self")) + + // Verify that the reference types are stored correctly + if let weakRefExp = weakRef as? ReferenceExp { + #expect(weakRefExp.captureReferenceType == "weak") + } else { + #expect(false, "Expected ReferenceExp type") + } + + if let unownedRefExp = unownedRef as? ReferenceExp { + #expect(unownedRefExp.captureReferenceType == "unowned") + } else { + #expect(false, "Expected ReferenceExp type") + } + } + + @Test("Reference method generates correct capture list syntax") + internal func testReferenceMethodGeneratesCorrectCaptureList() throws { + // Test weak reference in closure capture + let weakClosure = Closure( + capture: { + ParameterExp(unlabeled: VariableExp("self").reference("weak")) + }, + body: { + VariableExp("self").optional().call("handleData") { + ParameterExp(unlabeled: VariableExp("data")) + } + } + ) + + let weakGenerated = weakClosure.syntax.description + print("Weak closure generated:\n\(weakGenerated)") + #expect(weakGenerated.contains("[weak self]")) + + // Test unowned reference in closure capture + let unownedClosure = Closure( + capture: { + ParameterExp(unlabeled: VariableExp("self").reference("unowned")) + }, + body: { + VariableExp("self").call("handleData") { + ParameterExp(unlabeled: VariableExp("data")) + } + } + ) + + let unownedGenerated = unownedClosure.syntax.description + print("Unowned closure generated:\n\(unownedGenerated)") + #expect(unownedGenerated.contains("[unowned self]")) + } +} diff --git a/Tests/SyntaxKitTests/Unit/Utilities/String+Normalize.swift b/Tests/SyntaxKitTests/Unit/Utilities/String+Normalize.swift index 8b1251b..a0c0226 100644 --- a/Tests/SyntaxKitTests/Unit/Utilities/String+Normalize.swift +++ b/Tests/SyntaxKitTests/Unit/Utilities/String+Normalize.swift @@ -1,10 +1,155 @@ import Foundation +/// Options for string normalization +public struct NormalizeOptions: OptionSet, Sendable { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + /// Preserve newlines between sibling elements (useful for SwiftUI) + public static let preserveSiblingNewlines = NormalizeOptions(rawValue: 1 << 0) + + /// Preserve newlines after braces + public static let preserveBraceNewlines = NormalizeOptions(rawValue: 1 << 1) + + /// Preserve indentation structure + public static let preserveIndentation = NormalizeOptions(rawValue: 1 << 2) + + /// Default options for general code comparison + public static let `default`: NormalizeOptions = [] + + /// Options for SwiftUI code that needs to preserve some formatting + public static let swiftUI: NormalizeOptions = [.preserveSiblingNewlines, .preserveBraceNewlines] + + /// Options for structural comparison (ignores all formatting) + public static let structural: NormalizeOptions = [] +} + extension String { + /// Normalize whitespace and formatting for code comparison + /// - Parameter options: Normalization options to control formatting preservation + /// - Returns: Normalized string + internal func normalize(options: NormalizeOptions = .default) -> String { + var result = self + + // Always normalize colon spacing + result = result.replacingOccurrences(of: "\\s*:\\s*", with: ": ", options: .regularExpression) + + if options.contains(.preserveSiblingNewlines) { + // For SwiftUI, preserve newlines between sibling views but normalize other whitespace + // Replace multiple spaces with single space, but keep newlines + result = result.replacingOccurrences(of: "[ ]+", with: " ", options: .regularExpression) + + // Normalize newlines to single newlines + result = result.replacingOccurrences(of: "\\n+", with: "\n", options: .regularExpression) + + // Remove leading/trailing whitespace but preserve internal structure + result = result.trimmingCharacters(in: .whitespacesAndNewlines) + + // For SwiftUI, ensure consistent spacing around method chaining + // Add space after closing braces before method calls + result = result.replacingOccurrences(of: "}\\.", with: "} .", options: .regularExpression) + + // Ensure consistent spacing in ternary operators + result = result.replacingOccurrences(of: "\\?\\s*:", with: "? :", options: .regularExpression) + + // Add newlines between sibling views (Button elements) + result = result.replacingOccurrences( + of: "}\\s*Button", + with: "}\\nButton", + options: .regularExpression + ) + + // Add newline after method chaining + result = result.replacingOccurrences( + of: "\\.foregroundColor\\([^)]*\\)\\s*}", + with: ".foregroundColor($1)\\n}", + options: .regularExpression + ) + + // Normalize Task closure formatting + result = result.replacingOccurrences( + of: "Task\\s*{\\s*@MainActor", + with: "Task { @MainActor", + options: .regularExpression + ) + } else if options.contains(.preserveBraceNewlines) { + // Preserve newlines after braces but normalize other whitespace + result = result.replacingOccurrences(of: "[ ]+", with: " ", options: .regularExpression) + result = result.replacingOccurrences(of: "\\n+", with: "\n", options: .regularExpression) + result = result.trimmingCharacters(in: .whitespacesAndNewlines) + } else { + // Default behavior: normalize all whitespace including newlines + result = result.replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) + result = result.trimmingCharacters(in: .whitespacesAndNewlines) + } + + return result + } + + /// Legacy normalize function for backward compatibility internal func normalize() -> String { + normalize(options: .default) + } + + /// Structural comparison - removes all whitespace and formatting differences + /// Useful for comparing code structure without caring about formatting + internal func normalizeStructural() -> String { + self + .replacingOccurrences(of: "\\s+", with: "", options: .regularExpression) + .trimmingCharacters(in: .whitespacesAndNewlines) + } + /// Flexible comparison - allows for minor formatting differences + /// Useful for tests that should be resilient to formatting changes + internal func normalizeFlexible() -> String { self - .replacingOccurrences(of: "\\s*:\\s*", with: ": ", options: .regularExpression) - .replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) + .replacingOccurrences( + of: "\\s*:\\s*", + with: ":", + options: .regularExpression + ) // Normalize colons + .replacingOccurrences( + of: "\\s*=\\s*", + with: "=", + options: .regularExpression + ) // Normalize equals + .replacingOccurrences( + of: "\\s*->\\s*", + with: "->", + options: .regularExpression + ) // Normalize arrows + .replacingOccurrences( + of: "\\s*,\\s*", + with: ",", + options: .regularExpression + ) // Normalize commas + .replacingOccurrences( + of: "\\s*\\(\\s*", + with: "(", + options: .regularExpression + ) // Normalize opening parens + .replacingOccurrences( + of: "\\s*\\)\\s*", + with: ")", + options: .regularExpression + ) // Normalize closing parens + .replacingOccurrences( + of: "\\s*{\\s*", + with: "{", + options: .regularExpression + ) // Normalize opening braces + .replacingOccurrences( + of: "\\s*}\\s*", + with: "}", + options: .regularExpression + ) // Normalize closing braces + .replacingOccurrences( + of: "\\s+", + with: "", + options: .regularExpression + ) // Remove remaining whitespace .trimmingCharacters(in: .whitespacesAndNewlines) } } diff --git a/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift b/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift new file mode 100644 index 0000000..a8bb171 --- /dev/null +++ b/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift @@ -0,0 +1,193 @@ +// +// VariableCoverageTests.swift +// SyntaxKitTests +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax +import Testing + +@testable import SyntaxKit + +/// Test suite for improving code coverage of Variable-related functionality. +/// +/// This test suite focuses on testing edge cases and uncovered code paths +/// in the Variable extension files to ensure comprehensive test coverage. +internal final class VariableCoverageTests { + // MARK: - Variable+Modifiers.swift Coverage Tests + + /// Tests the "public" case in buildAccessModifier. + @Test("Build access modifier public") + internal func testBuildAccessModifierPublic() { + // Test the "public" case in buildAccessModifier + let variable = Variable(.let, name: "test", equals: "value") + .access("public") + + let syntax = variable.syntax + let description = syntax.description + + // Verify that the public access modifier is properly included + #expect(description.contains("public let test = \"value\"")) + } + + /// Tests the "internal" case in buildAccessModifier. + @Test("Build access modifier internal") + internal func testBuildAccessModifierInternal() { + // Test the "internal" case in buildAccessModifier + let variable = Variable(.let, name: "test", equals: "value") + .access("internal") + + let syntax = variable.syntax + let description = syntax.description + + // Verify that the internal access modifier is properly included + #expect(description.contains("internal let test = \"value\"")) + } + + /// Tests the "fileprivate" case in buildAccessModifier. + @Test("Build access modifier fileprivate") + internal func testBuildAccessModifierFileprivate() { + // Test the "fileprivate" case in buildAccessModifier + let variable = Variable(.let, name: "test", equals: "value") + .access("fileprivate") + + let syntax = variable.syntax + let description = syntax.description + + // Verify that the fileprivate access modifier is properly included + #expect(description.contains("fileprivate let test = \"value\"")) + } + + /// Tests the default case in buildAccessModifier (unknown access modifier). + @Test("Build access modifier default") + internal func testBuildAccessModifierDefault() { + // Test the default case in buildAccessModifier (unknown access modifier) + let variable = Variable(.let, name: "test", equals: "value") + .access("unknown") + + let syntax = variable.syntax + let description = syntax.description + + // Should fallback to public + #expect(description.contains("public let test = \"value\"")) + } + + // MARK: - Variable.swift Coverage Tests + + /// Tests the fallback type case in Variable initializer. + @Test("Variable initializer with fallback type") + internal func testVariableInitializerWithFallbackType() { + // Test the fallback type case in Variable initializer + // This tests when type is nil and defaultValue is not an Init + let variable = Variable(kind: .let, name: "test", defaultValue: VariableExp("value")) + + let syntax = variable.syntax + let description = syntax.description + + // Should use empty string as fallback type + #expect(description.contains("let test = value")) + } + + /// Tests the fallback case in buildExpressionFromValue. + @Test("Build expression from value fallback") + internal func testBuildExpressionFromValueFallback() { + // Test the fallback case in buildExpressionFromValue + // This tests when value is neither ExprCodeBlock nor ExprSyntax + + // Create a custom CodeBlock that doesn't conform to ExprCodeBlock + struct CustomCodeBlock: CodeBlock { + var syntax: SyntaxProtocol { + // Return something that's not ExprSyntax + DeclSyntax( + VariableDeclSyntax( + attributes: AttributeListSyntax([]), + modifiers: DeclModifierListSyntax([]), + bindingSpecifier: .keyword(.let, trailingTrivia: .space), + bindings: PatternBindingListSyntax([]) + ) + ) + } + } + + let customBlock = CustomCodeBlock() + let variable = Variable(kind: .let, name: "test", defaultValue: customBlock) + + let syntax = variable.syntax + let description = syntax.description + + // Should fallback to empty identifier + #expect(description.contains("let test = ")) + } + + // MARK: - Variable+Attributes.swift Coverage Tests + + /// Tests buildAttributeArguments with empty arguments array. + @Test("Build attribute arguments with empty array") + internal func testBuildAttributeArgumentsWithEmptyArray() { + // Test buildAttributeArguments with empty arguments array + let variable = Variable(.let, name: "test", equals: "value") + .attribute("TestAttribute", arguments: []) + + let syntax = variable.syntax + let description = syntax.description + + // Should include attribute without parentheses + #expect(description.contains("@TestAttribute")) + #expect(!description.contains("@TestAttribute()")) + } + + /// Tests buildAttributeArguments with multiple arguments. + @Test("Build attribute arguments with multiple arguments") + internal func testBuildAttributeArgumentsWithMultipleArguments() { + // Test buildAttributeArguments with multiple arguments + let variable = Variable(.let, name: "test", equals: "value") + .attribute("TestAttribute", arguments: ["arg1", "arg2", "arg3"]) + + let syntax = variable.syntax + let description = syntax.description + + // Should include attribute with comma-separated arguments + #expect(description.contains("@TestAttribute(arg1, arg2, arg3)")) + } + + /// Tests buildAttributeList with multiple attributes. + @Test("Build attribute list with multiple attributes") + internal func testBuildAttributeListWithMultipleAttributes() { + // Test buildAttributeList with multiple attributes + let variable = Variable(.let, name: "test", equals: "value") + .attribute("Attribute1") + .attribute("Attribute2", arguments: ["arg1"]) + .attribute("Attribute3", arguments: ["arg1", "arg2"]) + + let syntax = variable.syntax + let description = syntax.description + + // Should include all attributes + #expect(description.contains("@Attribute1")) + #expect(description.contains("@Attribute2(arg1)")) + #expect(description.contains("@Attribute3(arg1, arg2)")) + } +} From c62258326357a83312b7f835c579c3ee1c48b802 Mon Sep 17 00:00:00 2001 From: leogdion Date: Tue, 24 Jun 2025 19:02:43 -0400 Subject: [PATCH 09/10] Fixing Fatal Errors and Edge Cases (#83) --- Examples/Completed/conditionals/dsl.swift | 16 +-- Examples/Completed/for_loops/dsl.swift | 6 +- .../SKSampleMacroMacro.swift | 2 +- .../CodeBlocks/CodeBlock+ExprSyntax.swift | 11 +- .../CodeBlocks/CodeBlock+Generate.swift | 9 +- .../CodeBlocks/CodeBlockItemSyntax.Item.swift | 3 + .../CodeBlocks/CommentedCodeBlock.swift | 1 + .../Collections/Array+LiteralValue.swift | 7 +- .../SyntaxKit/Collections/ArrayLiteral.swift | 7 +- .../Collections/Dictionary+LiteralValue.swift | 7 +- .../Collections/DictionaryExpr.swift | 7 +- .../Collections/DictionaryLiteral.swift | 7 +- .../Collections/DictionaryValue.swift | 9 +- Sources/SyntaxKit/Collections/Tuple.swift | 14 +- .../Collections/TupleAssignment.swift | 7 +- .../SyntaxKit/Collections/TupleLiteral.swift | 7 +- Sources/SyntaxKit/ControlFlow/Do.swift | 7 + Sources/SyntaxKit/ControlFlow/For.swift | 42 +++--- Sources/SyntaxKit/ControlFlow/Guard.swift | 53 +++++-- .../SyntaxKit/ControlFlow/If+ElseBody.swift | 2 + Sources/SyntaxKit/ControlFlow/If.swift | 124 ++++++++++++++-- Sources/SyntaxKit/ControlFlow/Switch.swift | 12 +- .../SyntaxKit/ControlFlow/SwitchCase.swift | 16 ++- Sources/SyntaxKit/ControlFlow/While.swift | 126 +++++++++++----- Sources/SyntaxKit/Core/AccessModifier.swift | 63 ++++++++ .../SyntaxKit/Core/CaptureReferenceType.swift | 54 +++++++ .../SyntaxKit/Core/ExprCodeBlockBuilder.swift | 63 ++++++++ .../Core/PatternConvertibleBuilder.swift | 71 +++++++++ Sources/SyntaxKit/Declarations/Class.swift | 9 +- Sources/SyntaxKit/Declarations/Enum.swift | 9 +- .../SyntaxKit/Declarations/Extension.swift | 8 +- Sources/SyntaxKit/Declarations/Import.swift | 21 +-- Sources/SyntaxKit/Declarations/Init.swift | 13 +- Sources/SyntaxKit/Declarations/Protocol.swift | 9 +- Sources/SyntaxKit/Declarations/Struct.swift | 30 ++-- Sources/SyntaxKit/ErrorHandling/Catch.swift | 7 + .../SyntaxKit/Expressions/Assignment.swift | 11 +- Sources/SyntaxKit/Expressions/Call.swift | 10 +- .../Expressions/Closure+Capture.swift | 16 +-- Sources/SyntaxKit/Expressions/Closure.swift | 129 ++++++++++++++++- .../Expressions/FunctionCallExp.swift | 8 +- Sources/SyntaxKit/Expressions/Infix.swift | 80 ++++++++--- .../Literal+PatternConvertible.swift | 4 +- Sources/SyntaxKit/Expressions/Literal.swift | 7 +- .../NegatedPropertyAccessExp.swift | 8 +- .../Expressions/OptionalChainingExp.swift | 3 + .../SyntaxKit/Expressions/PlusAssign.swift | 11 +- .../Expressions/PropertyAccessExp.swift | 8 +- .../SyntaxKit/Expressions/ReferenceExp.swift | 8 +- Sources/SyntaxKit/Expressions/Return.swift | 43 ++++-- Sources/SyntaxKit/Expressions/Task.swift | 8 +- Sources/SyntaxKit/Functions/Function.swift | 18 +-- .../SyntaxKit/Parameters/ParameterExp.swift | 8 ++ Sources/SyntaxKit/Utilities/Case.swift | 11 +- .../SyntaxKit/Utilities/CodeBlockable.swift | 34 +++++ Sources/SyntaxKit/Utilities/Default.swift | 8 +- Sources/SyntaxKit/Utilities/Group.swift | 11 +- .../SyntaxKit/Utilities/Parenthesized.swift | 12 +- Sources/SyntaxKit/Utilities/Then.swift | 6 +- .../Variables/ComputedProperty.swift | 27 +--- .../Variable+LiteralInitializers.swift | 40 +----- .../Variables/Variable+Modifiers.swift | 18 +-- Sources/SyntaxKit/Variables/Variable.swift | 6 +- Sources/SyntaxKit/Variables/VariableExp.swift | 10 +- .../Integration/ConcurrencyExampleTests.swift | 30 ++-- .../ConditionalsExampleTests.swift | 136 ++++++++++++------ .../Integration/ForLoopsExampleTests.swift | 8 +- .../Integration/SwiftUIExampleTests.swift | 14 +- .../Unit/ControlFlow/ConditionalsTests.swift | 38 ++++- .../Unit/ControlFlow/ForLoopTests.swift | 8 +- .../Unit/EdgeCases/EdgeCaseTests.swift | 126 +++++++++++++--- .../EdgeCases/EdgeCaseTestsExpressions.swift | 14 +- .../ClosureCaptureCoverageTests.swift | 24 +--- .../ReferenceExp/ReferenceExpBasicTests.swift | 58 ++------ .../ReferenceExpComplexTests.swift | 12 +- .../ReferenceExpFunctionTests.swift | 12 +- .../ReferenceExpLiteralTests.swift | 16 +-- .../ReferenceExpPropertyTests.swift | 16 +-- .../FrameworkCompatibilityTests.swift | 4 +- .../OptionsMacroIntegrationTests.swift | 37 ++--- .../Unit/SwiftUIFeatureTests.swift | 16 +-- .../Variables/VariableCoverageTests.swift | 20 +-- 82 files changed, 1393 insertions(+), 618 deletions(-) create mode 100644 Sources/SyntaxKit/Core/AccessModifier.swift create mode 100644 Sources/SyntaxKit/Core/CaptureReferenceType.swift create mode 100644 Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift create mode 100644 Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift create mode 100644 Sources/SyntaxKit/Utilities/CodeBlockable.swift diff --git a/Examples/Completed/conditionals/dsl.swift b/Examples/Completed/conditionals/dsl.swift index a666c2a..70263e0 100644 --- a/Examples/Completed/conditionals/dsl.swift +++ b/Examples/Completed/conditionals/dsl.swift @@ -23,7 +23,7 @@ Group { Call("print", "Good job!") } If { - Infix("score", ">=", 70) + try Infix("score", ">=", 70) } then: { Call("print", "Passing") } @@ -172,24 +172,24 @@ Infix("board[24]", "-=", 8) Variable(.var, name: "square", equals: 0) Variable(.var, name: "diceRoll", equals: 0) While { - Infix("square", "!=", "finalSquare") + try Infix("square", "!=", "finalSquare") } then: { Assignment("diceRoll", "+", 1) If { - Infix("diceRoll", "==", 7) + try Infix("diceRoll", "==", 7) } then: { Assignment("diceRoll", 1) } - Switch(Infix("square", "+", "diceRoll")) { + Switch(try Infix("square", "+", "diceRoll")) { SwitchCase("finalSquare") { Break() } - SwitchCase(Infix("newSquare", ">", "finalSquare")) { + SwitchCase(try Infix("newSquare", ">", "finalSquare")) { Continue() } Default { - Infix("square", "+=", "diceRoll") - Infix("square", "+=", "board[square]") + try Infix("square", "+=", "diceRoll") + try Infix("square", "+=", "board[square]") } } } @@ -216,7 +216,7 @@ For { } in: { Literal.array([Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), Literal.integer(9), Literal.integer(10)]) } where: { - Infix("number", "%", 2) + try Infix("number", "%", 2) } then: { Call("print", "Even number: \\(number)") } diff --git a/Examples/Completed/for_loops/dsl.swift b/Examples/Completed/for_loops/dsl.swift index 4c8bf36..db06009 100644 --- a/Examples/Completed/for_loops/dsl.swift +++ b/Examples/Completed/for_loops/dsl.swift @@ -40,8 +40,8 @@ Group { Variable(.let, name: "numbers", equals: Literal.array([Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), Literal.integer(9), Literal.integer(10)])) For(VariableExp("number"), in: VariableExp("numbers"), where: { - Infix("==") { - Infix("%") { + try Infix("==") { + try Infix("%") { VariableExp("number") Literal.integer(2) } @@ -68,4 +68,4 @@ Group { ParameterExp(unlabeled: "\"\\(name): \\(score)\"") } }) -} \ No newline at end of file +} diff --git a/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift b/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift index 014fb7e..e531bec 100644 --- a/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift +++ b/Macros/SKSampleMacro/Sources/SKSampleMacroMacros/SKSampleMacroMacro.swift @@ -25,7 +25,7 @@ public struct StringifyMacro: ExpressionMacro { } return Tuple{ - Infix("+") { + try Infix("+") { VariableExp(first.description) VariableExp(second.description) } diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlock+ExprSyntax.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlock+ExprSyntax.swift index b8b9f30..679e112 100644 --- a/Sources/SyntaxKit/CodeBlocks/CodeBlock+ExprSyntax.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlock+ExprSyntax.swift @@ -35,8 +35,8 @@ extension CodeBlock { /// If the underlying syntax already *is* an `ExprSyntax`, it is returned directly. If the /// underlying syntax is a bare `TokenSyntax` (commonly the case for `VariableExp` which /// produces an identifier token), we wrap it in a `DeclReferenceExprSyntax` so that it becomes - /// a valid expression node. Any other kind of syntax results in a runtime error, because it - /// cannot be represented as an expression (e.g. declarations or statements). + /// a valid expression node. For any other kind of syntax, we create a default empty expression + /// to prevent crashes while still allowing code generation to continue. public var expr: ExprSyntax { if let expr = self.syntax.as(ExprSyntax.self) { return expr @@ -46,6 +46,11 @@ extension CodeBlock { return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) } - fatalError("CodeBlock of type \(type(of: self.syntax)) cannot be represented as ExprSyntax") + // Fallback for unsupported syntax types - create a default expression + // This prevents crashes while still allowing code generation to continue + #warning( + "TODO: Review fallback for unsupported syntax types - consider if this should be an error instead" + ) + return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) } } diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift index adfd488..aaaa936 100644 --- a/Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlock+Generate.swift @@ -45,10 +45,13 @@ extension CodeBlock { if let convertedItem = CodeBlockItemSyntax.Item.create(from: self.syntax) { item = convertedItem } else { - fatalError( - "Unsupported syntax type at top level: \(type(of: self.syntax)) (\(self.syntax)) " - + "generating from \(self)" + // Fallback for unsupported syntax types - create an empty code block + // This prevents crashes while still allowing code generation to continue + #warning( + "TODO: Review fallback for unsupported syntax types - consider if this should be an error instead" ) + let emptyExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) + item = .expr(emptyExpr) } statements = CodeBlockItemListSyntax([ CodeBlockItemSyntax(item: item, trailingTrivia: .newline) diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift index 17e72fe..1ed448a 100644 --- a/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlockItemSyntax.Item.swift @@ -47,6 +47,9 @@ extension CodeBlockItemSyntax.Item { } else if let switchCase = syntax.as(SwitchCaseSyntax.self) { // Wrap SwitchCaseSyntax in a SwitchExprSyntax and treat it as an expression // This is a fallback for when SwitchCase is used standalone + #warning( + "TODO: Review fallback for SwitchCase used standalone - consider if this should be an error instead" + ) let switchExpr = SwitchExprSyntax( switchKeyword: .keyword(.switch, trailingTrivia: .space), subject: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier("_"))), diff --git a/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift index 4b3d653..1df7dcd 100644 --- a/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift +++ b/Sources/SyntaxKit/CodeBlocks/CommentedCodeBlock.swift @@ -60,6 +60,7 @@ internal struct CommentedCodeBlock: CodeBlock { guard let firstToken = base.syntax.firstToken(viewMode: .sourceAccurate) else { // Fallback – no tokens? return original syntax + #warning("TODO: Review fallback for no tokens - consider if this should be an error instead") return base.syntax } diff --git a/Sources/SyntaxKit/Collections/Array+LiteralValue.swift b/Sources/SyntaxKit/Collections/Array+LiteralValue.swift index 9b75416..64ad042 100644 --- a/Sources/SyntaxKit/Collections/Array+LiteralValue.swift +++ b/Sources/SyntaxKit/Collections/Array+LiteralValue.swift @@ -29,10 +29,15 @@ import Foundation -extension Array: LiteralValue where Element == String { +extension Array: LiteralValue, CodeBlockable where Element == String { /// The Swift type name for an array of strings. public var typeName: String { "[String]" } + /// The code block representation of this array of strings. + public var codeBlock: CodeBlock { + Literal.array(self.map { .string($0) }) + } + /// Renders this array as a Swift literal string with proper escaping. public var literalString: String { let elements = self.map { element in diff --git a/Sources/SyntaxKit/Collections/ArrayLiteral.swift b/Sources/SyntaxKit/Collections/ArrayLiteral.swift index 4117858..f419dae 100644 --- a/Sources/SyntaxKit/Collections/ArrayLiteral.swift +++ b/Sources/SyntaxKit/Collections/ArrayLiteral.swift @@ -30,7 +30,7 @@ import Foundation /// An array literal value that can be used as a literal. -public struct ArrayLiteral: LiteralValue { +public struct ArrayLiteral: LiteralValue, CodeBlockable { public let elements: [Literal] /// Creates an array with the given elements. @@ -39,6 +39,11 @@ public struct ArrayLiteral: LiteralValue { self.elements = elements } + /// The code block representation of this array literal. + public var codeBlock: CodeBlock { + Literal.array(elements) + } + /// The Swift type name for this array. public var typeName: String { if elements.isEmpty { diff --git a/Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift b/Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift index 183492f..48082e1 100644 --- a/Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift +++ b/Sources/SyntaxKit/Collections/Dictionary+LiteralValue.swift @@ -29,10 +29,15 @@ import Foundation -extension Dictionary: LiteralValue where Key == Int, Value == String { +extension Dictionary: LiteralValue, CodeBlockable where Key == Int, Value == String { /// The Swift type name for a dictionary mapping integers to strings. public var typeName: String { "[Int: String]" } + /// The code block representation of this dictionary. + public var codeBlock: CodeBlock { + Literal.dictionary(self.map { (.integer($0.key), .string($0.value)) }) + } + /// Renders this dictionary as a Swift literal string with proper escaping. public var literalString: String { let elements = self.map { key, value in diff --git a/Sources/SyntaxKit/Collections/DictionaryExpr.swift b/Sources/SyntaxKit/Collections/DictionaryExpr.swift index 0006f55..2b751b7 100644 --- a/Sources/SyntaxKit/Collections/DictionaryExpr.swift +++ b/Sources/SyntaxKit/Collections/DictionaryExpr.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A dictionary expression that can contain both Literal types and CodeBlock types. -public struct DictionaryExpr: CodeBlock, LiteralValue { +public struct DictionaryExpr: CodeBlock, LiteralValue, CodeBlockable { private let elements: [(DictionaryValue, DictionaryValue)] /// Creates a dictionary expression with the given key-value pairs. @@ -39,6 +39,11 @@ public struct DictionaryExpr: CodeBlock, LiteralValue { self.elements = elements } + /// The code block representation of this dictionary expression. + public var codeBlock: CodeBlock { + self + } + /// The Swift type name for this dictionary. public var typeName: String { if elements.isEmpty { diff --git a/Sources/SyntaxKit/Collections/DictionaryLiteral.swift b/Sources/SyntaxKit/Collections/DictionaryLiteral.swift index 03dc8a8..2843ec2 100644 --- a/Sources/SyntaxKit/Collections/DictionaryLiteral.swift +++ b/Sources/SyntaxKit/Collections/DictionaryLiteral.swift @@ -30,7 +30,7 @@ import Foundation /// A dictionary literal value that can be used as a literal. -public struct DictionaryLiteral: LiteralValue { +public struct DictionaryLiteral: LiteralValue, CodeBlockable { public let elements: [(Literal, Literal)] /// Creates a dictionary with the given key-value pairs. @@ -39,6 +39,11 @@ public struct DictionaryLiteral: LiteralValue { self.elements = elements } + /// The code block representation of this dictionary literal. + public var codeBlock: CodeBlock { + Literal.dictionary(elements) + } + /// The Swift type name for this dictionary. public var typeName: String { if elements.isEmpty { diff --git a/Sources/SyntaxKit/Collections/DictionaryValue.swift b/Sources/SyntaxKit/Collections/DictionaryValue.swift index b8bb8e2..b1ac438 100644 --- a/Sources/SyntaxKit/Collections/DictionaryValue.swift +++ b/Sources/SyntaxKit/Collections/DictionaryValue.swift @@ -48,7 +48,7 @@ extension CodeBlock where Self: DictionaryValue { /// Converts this code block to an expression syntax. /// If the code block is already an expression, returns it directly. /// If it's a token, wraps it in a declaration reference expression. - /// Otherwise, throws a fatal error. + /// Otherwise, creates a default empty expression to prevent crashes. public var exprSyntax: ExprSyntax { if let expr = self.syntax.as(ExprSyntax.self) { return expr @@ -58,7 +58,12 @@ extension CodeBlock where Self: DictionaryValue { return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(token.text))) } - fatalError("CodeBlock of type \(type(of: self.syntax)) cannot be represented as ExprSyntax") + // Fallback for unsupported syntax types - create a default expression + // This prevents crashes while still allowing dictionary operations to continue + #warning( + "TODO: Review fallback for unsupported syntax types - consider if this should be an error instead" + ) + return ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) } } diff --git a/Sources/SyntaxKit/Collections/Tuple.swift b/Sources/SyntaxKit/Collections/Tuple.swift index 622673e..ab71880 100644 --- a/Sources/SyntaxKit/Collections/Tuple.swift +++ b/Sources/SyntaxKit/Collections/Tuple.swift @@ -35,12 +35,10 @@ public struct Tuple: CodeBlock { private var isAsync: Bool = false private var isThrowing: Bool = false - /// Creates a tuple expression comprising the supplied elements. - /// - Parameter content: A ``CodeBlockBuilder`` producing the tuple elements **in order**. - /// Elements may be any `CodeBlock` that can be represented as an expression (see - /// `CodeBlock.expr`). - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.elements = content() + /// Creates a tuple. + /// - Parameter content: A ``CodeBlockBuilder`` that provides the elements of the tuple. + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.elements = try content() } /// Creates a tuple pattern for switch cases. @@ -80,10 +78,6 @@ public struct Tuple: CodeBlock { } public var syntax: SyntaxProtocol { - guard !elements.isEmpty else { - fatalError("Tuple must contain at least one element.") - } - let list = TupleExprElementListSyntax( elements.enumerated().map { index, block in let elementExpr: ExprSyntax diff --git a/Sources/SyntaxKit/Collections/TupleAssignment.swift b/Sources/SyntaxKit/Collections/TupleAssignment.swift index 7a96427..e765f21 100644 --- a/Sources/SyntaxKit/Collections/TupleAssignment.swift +++ b/Sources/SyntaxKit/Collections/TupleAssignment.swift @@ -83,9 +83,12 @@ public struct TupleAssignment: CodeBlock { private func generateAsyncSetSyntax() -> SyntaxProtocol { // Generate a single async let tuple destructuring assignment guard let tuple = value as? Tuple, elements.count == tuple.elements.count else { - fatalError( - "asyncSet requires a Tuple value with the same number of elements as the assignment." + // Fallback to regular syntax if conditions aren't met for asyncSet + // This provides a more robust API instead of crashing + #warning( + "TODO: Review fallback for asyncSet conditions - consider if this should be an error instead" ) + return generateRegularSyntax() } // Use helpers from AsyncSet diff --git a/Sources/SyntaxKit/Collections/TupleLiteral.swift b/Sources/SyntaxKit/Collections/TupleLiteral.swift index 4bbba1a..0c3efaf 100644 --- a/Sources/SyntaxKit/Collections/TupleLiteral.swift +++ b/Sources/SyntaxKit/Collections/TupleLiteral.swift @@ -30,7 +30,7 @@ import Foundation /// A tuple literal value that can be used as a literal. -public struct TupleLiteral: LiteralValue { +public struct TupleLiteral: LiteralValue, CodeBlockable { public let elements: [Literal?] /// Creates a tuple with the given elements. @@ -39,6 +39,11 @@ public struct TupleLiteral: LiteralValue { self.elements = elements } + /// The code block representation of this tuple literal. + public var codeBlock: CodeBlock { + Literal.tuple(elements) + } + /// The Swift type name for this tuple. public var typeName: String { let elementTypes = elements.map { element in diff --git a/Sources/SyntaxKit/ControlFlow/Do.swift b/Sources/SyntaxKit/ControlFlow/Do.swift index d9279db..42307f3 100644 --- a/Sources/SyntaxKit/ControlFlow/Do.swift +++ b/Sources/SyntaxKit/ControlFlow/Do.swift @@ -35,6 +35,13 @@ public struct Do: CodeBlock { private let body: [CodeBlock] private let catchClauses: CatchClauseListSyntax + /// Creates a `do` statement. + /// - Parameter body: A ``CodeBlockBuilder`` that provides the body of the `do` block. + public init(@CodeBlockBuilderResult _ body: () throws -> [CodeBlock]) rethrows { + self.body = try body() + self.catchClauses = CatchClauseListSyntax([]) + } + /// Creates a `do-catch` statement. /// - Parameters: /// - body: A ``CodeBlockBuilder`` that provides the body of the do block. diff --git a/Sources/SyntaxKit/ControlFlow/For.swift b/Sources/SyntaxKit/ControlFlow/For.swift index ff3a5d1..0bcc4b5 100644 --- a/Sources/SyntaxKit/ControlFlow/For.swift +++ b/Sources/SyntaxKit/ControlFlow/For.swift @@ -40,45 +40,37 @@ public struct For: CodeBlock { /// - Parameters: /// - pattern: A `CodeBlock` that also conforms to `PatternConvertible` for the loop variable(s). /// - sequence: A `CodeBlock` that produces the sequence to iterate over. - /// - whereClause: An optional `CodeBlockBuilder` that produces the where clause condition. + /// - whereClause: A `CodeBlockBuilder` that produces the where clause condition. /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. public init( _ pattern: any CodeBlock & PatternConvertible, in sequence: CodeBlock, - @CodeBlockBuilderResult where whereClause: () -> [CodeBlock] = { [] }, - @CodeBlockBuilderResult then: () -> [CodeBlock] - ) { + @CodeBlockBuilderResult where whereClause: () throws -> [CodeBlock], + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { self.pattern = pattern self.sequence = sequence - let whereBlocks = whereClause() + let whereBlocks = try whereClause() self.whereClause = whereBlocks.isEmpty ? nil : whereBlocks[0] - self.body = then() + self.body = try then() } - /// Creates a `for-in` loop statement with a closure-based pattern. + /// Creates a `for-in` loop statement without a where clause. /// - Parameters: - /// - pattern: A `CodeBlockBuilder` that produces the pattern for the loop variable(s). + /// - pattern: A `CodeBlock` that also conforms to `PatternConvertible` for the loop variable(s). /// - sequence: A `CodeBlock` that produces the sequence to iterate over. - /// - whereClause: An optional `CodeBlockBuilder` that produces the where clause condition. /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. public init( - @CodeBlockBuilderResult _ pattern: () -> [CodeBlock], + _ pattern: any CodeBlock & PatternConvertible, in sequence: CodeBlock, - @CodeBlockBuilderResult where whereClause: () -> [CodeBlock] = { [] }, - @CodeBlockBuilderResult then: () -> [CodeBlock] - ) { - let patterns = pattern() - guard patterns.count == 1 else { - fatalError("For requires exactly one pattern CodeBlock") - } - guard let patternBlock = patterns[0] as? (any CodeBlock & PatternConvertible) else { - fatalError("For pattern must implement both CodeBlock and PatternConvertible protocols") - } - self.pattern = patternBlock - self.sequence = sequence - let whereBlocks = whereClause() - self.whereClause = whereBlocks.isEmpty ? nil : whereBlocks[0] - self.body = then() + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + try self.init( + pattern, + in: sequence, + where: [CodeBlock].init, + then: then + ) } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/ControlFlow/Guard.swift b/Sources/SyntaxKit/ControlFlow/Guard.swift index b5e9bf5..c64cbe9 100644 --- a/Sources/SyntaxKit/ControlFlow/Guard.swift +++ b/Sources/SyntaxKit/ControlFlow/Guard.swift @@ -36,27 +36,52 @@ public struct Guard: CodeBlock { /// Creates a `guard` statement. /// - Parameters: - /// - condition: A builder that returns one or more ``CodeBlock`` items representing the guard - /// conditions. - /// - elseBody: Builder that produces the statements inside the `else` block. + /// - condition: A ``CodeBlockBuilder`` that provides the condition expression. + /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. public init( - @CodeBlockBuilderResult _ condition: () -> [CodeBlock], - @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] - ) { - let allConditions = condition() - guard !allConditions.isEmpty else { - fatalError("Guard requires at least one condition CodeBlock") + @CodeBlockBuilderResult _ condition: () throws -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + let allConditions = try condition() + if allConditions.isEmpty { + // Use true as default condition when no conditions are provided + self.conditions = [Literal.boolean(true)] + } else { + self.conditions = allConditions } - self.conditions = allConditions - self.elseBody = elseBody() + self.elseBody = try elseBody() + } + + /// Creates a `guard` statement without a condition (uses true as default). + /// - Parameters: + /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + public init( + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + try self.init( + [CodeBlock].init, + else: elseBody + ) + } + + /// Creates a `guard` statement with a string condition. + /// - Parameters: + /// - condition: The condition as a string. + /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + public init( + _ condition: String, + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + self.conditions = [VariableExp(condition)] + self.elseBody = try elseBody() } /// Convenience initializer that accepts a single condition ``CodeBlock``. public init( _ condition: CodeBlock, - @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] - ) { - self.init({ condition }, else: elseBody) + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + try self.init({ condition }, else: elseBody) } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift b/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift index 7abd91c..223cd5b 100644 --- a/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift +++ b/Sources/SyntaxKit/ControlFlow/If+ElseBody.swift @@ -84,6 +84,8 @@ extension If { return IfExprSyntax.ElseBody(nestedIf) } else { // Fallback to empty code block + #warning( + "TODO: Review fallback to empty code block - consider if this should be an error instead") return IfExprSyntax.ElseBody( CodeBlockSyntax( leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), diff --git a/Sources/SyntaxKit/ControlFlow/If.swift b/Sources/SyntaxKit/ControlFlow/If.swift index 65bcca7..d5d87a8 100644 --- a/Sources/SyntaxKit/ControlFlow/If.swift +++ b/Sources/SyntaxKit/ControlFlow/If.swift @@ -35,6 +35,36 @@ public struct If: CodeBlock { internal let body: [CodeBlock] internal let elseBody: [CodeBlock]? + /// Convenience initializer that keeps the previous API: pass the condition directly. + public init( + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + try self.init({ Literal.boolean(true) }, then: then) + } + + /// Convenience initializer that keeps the previous API: pass the condition directly. + public init( + @CodeBlockBuilderResult then: () throws -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + try self.init({ Literal.boolean(true) }, then: then, else: elseBody) + } + + /// Creates an `if` statement with optional `else`. + /// - Parameters: + /// - condition: A single `CodeBlock` produced by the builder that describes the `if` condition. + /// - then: Builder that produces the body for the `if` branch. + public init( + @CodeBlockBuilderResult _ condition: () -> [CodeBlock], + @CodeBlockBuilderResult then: () -> [CodeBlock] + ) { + self.init( + condition, + then: then, + else: [CodeBlock].init + ) + } + /// Creates an `if` statement with optional `else`. /// - Parameters: /// - condition: A single `CodeBlock` produced by the builder that describes the `if` condition. @@ -45,13 +75,15 @@ public struct If: CodeBlock { public init( @CodeBlockBuilderResult _ condition: () -> [CodeBlock], @CodeBlockBuilderResult then: () -> [CodeBlock], - @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } + @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] ) { let allConditions = condition() - guard !allConditions.isEmpty else { - fatalError("If requires at least one condition CodeBlock") + if allConditions.isEmpty { + // Use true as default condition when no conditions are provided + self.conditions = [Literal.boolean(true)] + } else { + self.conditions = allConditions } - self.conditions = allConditions self.body = then() let generatedElse = elseBody() self.elseBody = generatedElse.isEmpty ? nil : generatedElse @@ -60,10 +92,86 @@ public struct If: CodeBlock { /// Convenience initializer that keeps the previous API: pass the condition directly. public init( _ condition: CodeBlock, - @CodeBlockBuilderResult then: () -> [CodeBlock], - @CodeBlockBuilderResult else elseBody: () -> [CodeBlock] = { [] } - ) { - self.init({ condition }, then: then, else: elseBody) + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + try self.init({ condition }, then: then) + } + + /// Convenience initializer that keeps the previous API: pass the condition directly. + public init( + _ condition: CodeBlock, + @CodeBlockBuilderResult then: () throws -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + try self.init({ condition }, then: then, else: elseBody) + } + + /// Creates an `if` statement. + /// - Parameters: + /// - condition: A ``CodeBlockBuilder`` that provides the condition expression. + /// - then: A ``CodeBlockBuilder`` that provides the body when the condition is true. + public init( + @CodeBlockBuilderResult _ condition: () throws -> [CodeBlock], + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + try self.init( + condition, + then: then, + else: [CodeBlock].init + ) + } + + /// Creates an `if` statement. + /// - Parameters: + /// - condition: A ``CodeBlockBuilder`` that provides the condition expression. + /// - then: A ``CodeBlockBuilder`` that provides the body when the condition is true. + /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + public init( + @CodeBlockBuilderResult _ condition: () throws -> [CodeBlock], + @CodeBlockBuilderResult then: () throws -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + let allConditions = try condition() + if allConditions.isEmpty { + // Use true as default condition when no conditions are provided + self.conditions = [Literal.boolean(true)] + } else { + self.conditions = allConditions + } + self.body = try then() + let generatedElse = try elseBody() + self.elseBody = generatedElse.isEmpty ? nil : generatedElse + } + + /// Creates an `if` statement with a string condition. + /// - Parameters: + /// - condition: The condition as a string. + /// - then: A ``CodeBlockBuilder`` that provides the body when the condition is true. + public init( + _ condition: String, + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + try self.init( + condition, + then: then, + else: [CodeBlock].init + ) + } + + /// Creates an `if` statement with a string condition. + /// - Parameters: + /// - condition: The condition as a string. + /// - then: A ``CodeBlockBuilder`` that provides the body when the condition is true. + /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + public init( + _ condition: String, + @CodeBlockBuilderResult then: () throws -> [CodeBlock], + @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] + ) rethrows { + self.conditions = [VariableExp(condition)] + self.body = try then() + let generatedElse = try elseBody() + self.elseBody = generatedElse.isEmpty ? nil : generatedElse } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/ControlFlow/Switch.swift b/Sources/SyntaxKit/ControlFlow/Switch.swift index 1def183..79d9ad3 100644 --- a/Sources/SyntaxKit/ControlFlow/Switch.swift +++ b/Sources/SyntaxKit/ControlFlow/Switch.swift @@ -38,18 +38,22 @@ public struct Switch: CodeBlock { /// - Parameters: /// - expression: The expression to switch on. /// - content: A ``CodeBlockBuilder`` that provides the cases for the switch. - public init(_ expression: CodeBlock, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + public init(_ expression: CodeBlock, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) + rethrows + { self.expression = expression - self.cases = content() + self.cases = try content() } /// Convenience initializer that accepts a string expression. /// - Parameters: /// - expression: The string expression to switch on. /// - content: A ``CodeBlockBuilder`` that provides the cases for the switch. - public init(_ expression: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + public init(_ expression: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) + rethrows + { self.expression = VariableExp(expression) - self.cases = content() + self.cases = try content() } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/ControlFlow/SwitchCase.swift b/Sources/SyntaxKit/ControlFlow/SwitchCase.swift index 5e10279..4999e8c 100644 --- a/Sources/SyntaxKit/ControlFlow/SwitchCase.swift +++ b/Sources/SyntaxKit/ControlFlow/SwitchCase.swift @@ -39,9 +39,11 @@ public struct SwitchCase: CodeBlock { /// - patterns: The patterns to match for the case. Can be `PatternConvertible`, /// `CodeBlock`, or `SwitchLet` for value binding. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. - public init(_ patterns: Any..., @CodeBlockBuilderResult content: () -> [CodeBlock]) { + public init(_ patterns: Any..., @CodeBlockBuilderResult content: () throws -> [CodeBlock]) + rethrows + { self.patterns = patterns - self.body = content() + self.body = try content() } /// Creates a `case` for a `switch` statement with a builder closure for the conditional. @@ -49,11 +51,11 @@ public struct SwitchCase: CodeBlock { /// - conditional: A ``CodeBlockBuilder`` that provides the conditional patterns for the case. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. public init( - @CodeBlockBuilderResult conditional: () -> [Any], - @CodeBlockBuilderResult content: () -> [CodeBlock] - ) { - self.patterns = conditional() - self.body = content() + @CodeBlockBuilderResult conditional: () throws -> [CodeBlock], + @CodeBlockBuilderResult content: () throws -> [CodeBlock] + ) rethrows { + self.patterns = try conditional() + self.body = try content() } public var switchCaseSyntax: SwitchCaseSyntax { diff --git a/Sources/SyntaxKit/ControlFlow/While.swift b/Sources/SyntaxKit/ControlFlow/While.swift index 44080be..4bd03b6 100644 --- a/Sources/SyntaxKit/ControlFlow/While.swift +++ b/Sources/SyntaxKit/ControlFlow/While.swift @@ -31,41 +31,87 @@ import SwiftSyntax /// A `while` loop statement. public struct While: CodeBlock { - private let condition: CodeBlock + public enum Kind { + case `while` + case repeatWhile + } + + private let condition: any ExprCodeBlock private let body: [CodeBlock] + private let kind: Kind - /// Creates a `while` loop statement. + /// Creates a `while` loop statement with an expression condition. /// - Parameters: - /// - condition: A `CodeBlockBuilder` that produces the condition expression. + /// - condition: The condition expression that conforms to ExprCodeBlock. + /// - kind: The kind of loop (default is `.while`). /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. public init( - @CodeBlockBuilderResult _ condition: () -> [CodeBlock], - @CodeBlockBuilderResult then: () -> [CodeBlock] - ) { - let conditions = condition() - guard conditions.count == 1 else { - fatalError("While requires exactly one condition CodeBlock") - } - self.condition = conditions[0] - self.body = then() + _ condition: any ExprCodeBlock, + kind: Kind = .while, + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + self.condition = condition + self.body = try then() + self.kind = kind } - /// Convenience initializer that accepts a single condition directly. + /// Creates a `while` loop statement with a builder closure for the condition. /// - Parameters: - /// - condition: The condition expression. + /// - condition: A `CodeBlockBuilder` that produces exactly one condition expression. + /// - kind: The kind of loop (default is `.while`). /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. public init( - _ condition: CodeBlock, - @CodeBlockBuilderResult then: () -> [CodeBlock] - ) { - self.init({ condition }, then: then) + kind: Kind = .while, + @ExprCodeBlockBuilder _ condition: () throws -> any ExprCodeBlock, + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + self.condition = try condition() + self.body = try then() + self.kind = kind + } + + /// Creates a `while` loop. + /// - Parameters: + /// - condition: A ``CodeBlockBuilder`` that provides the condition expression. + /// - kind: The kind of loop (default is `.while`). + /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. + @available( + *, deprecated, + message: "Use While(kind:condition:) with ExprCodeBlockBuilder instead for better type safety" + ) + public init( + kind: Kind = .while, + @CodeBlockBuilderResult _ condition: () throws -> [CodeBlock], + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + let conditionBlocks = try condition() + let firstCondition = conditionBlocks.first as? any ExprCodeBlock ?? Literal.boolean(true) + self.condition = firstCondition + self.body = try then() + self.kind = kind + } + + /// Creates a `while` loop with a string condition. + /// - Parameters: + /// - condition: The condition as a string. + /// - kind: The kind of loop (default is `.while`). + /// - then: A ``CodeBlockBuilder`` that provides the body of the loop. + @available( + *, deprecated, + message: "Use While(VariableExp(condition), kind:then:) instead for better type safety" + ) + public init( + _ condition: String, + kind: Kind = .while, + @CodeBlockBuilderResult then: () throws -> [CodeBlock] + ) rethrows { + self.condition = VariableExp(condition) + self.body = try then() + self.kind = kind } public var syntax: SyntaxProtocol { - let conditionExpr = ExprSyntax( - fromProtocol: condition.syntax.as(ExprSyntax.self) - ?? DeclReferenceExprSyntax(baseName: .identifier("")) - ) + let conditionExpr = condition.exprSyntax let bodyBlock = CodeBlockSyntax( leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), @@ -85,18 +131,30 @@ public struct While: CodeBlock { rightBrace: .rightBraceToken(leadingTrivia: .newline) ) - return StmtSyntax( - WhileStmtSyntax( - whileKeyword: .keyword(.while, trailingTrivia: .space), - conditions: ConditionElementListSyntax( - [ - ConditionElementSyntax( - condition: .expression(conditionExpr) - ) - ] - ), - body: bodyBlock + switch kind { + case .repeatWhile: + return StmtSyntax( + RepeatWhileStmtSyntax( + repeatKeyword: .keyword(.repeat, trailingTrivia: .space), + body: bodyBlock, + whileKeyword: .keyword(.while, trailingTrivia: .space), + condition: conditionExpr + ) ) - ) + case .while: + return StmtSyntax( + WhileStmtSyntax( + whileKeyword: .keyword(.while, trailingTrivia: .space), + conditions: ConditionElementListSyntax( + [ + ConditionElementSyntax( + condition: .expression(conditionExpr) + ) + ] + ), + body: bodyBlock + ) + ) + } } } diff --git a/Sources/SyntaxKit/Core/AccessModifier.swift b/Sources/SyntaxKit/Core/AccessModifier.swift new file mode 100644 index 0000000..edd3631 --- /dev/null +++ b/Sources/SyntaxKit/Core/AccessModifier.swift @@ -0,0 +1,63 @@ +// +// AccessModifier.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Represents Swift access modifiers. +public enum AccessModifier: CaseIterable { + case `public` + case `private` + case `internal` + case `fileprivate` + case `open` + + /// Returns the corresponding SwiftSyntax Keyword for this access modifier. + public var keyword: Keyword { + switch self { + case .public: + return .public + case .private: + return .private + case .internal: + return .internal + case .fileprivate: + return .fileprivate + case .open: + return .open + } + } +} + +extension Keyword { + /// Creates a Keyword from an AccessModifier. + /// - Parameter accessModifier: The access modifier to convert. + public init(_ accessModifier: AccessModifier) { + self = accessModifier.keyword + } +} diff --git a/Sources/SyntaxKit/Core/CaptureReferenceType.swift b/Sources/SyntaxKit/Core/CaptureReferenceType.swift new file mode 100644 index 0000000..582eba6 --- /dev/null +++ b/Sources/SyntaxKit/Core/CaptureReferenceType.swift @@ -0,0 +1,54 @@ +// +// CaptureReferenceType.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// Represents Swift capture reference types for closures. +public enum CaptureReferenceType: CaseIterable { + case weak + case unowned + + /// Returns the corresponding SwiftSyntax Keyword for this capture reference type. + public var keyword: Keyword { + switch self { + case .weak: + return .weak + case .unowned: + return .unowned + } + } +} + +extension Keyword { + /// Creates a Keyword from a CaptureReferenceType. + /// - Parameter captureReferenceType: The capture reference type to convert. + public init(_ captureReferenceType: CaptureReferenceType) { + self = captureReferenceType.keyword + } +} diff --git a/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift b/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift new file mode 100644 index 0000000..317a0d8 --- /dev/null +++ b/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift @@ -0,0 +1,63 @@ +// +// ExprCodeBlockBuilder.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A result builder that produces exactly one `ExprCodeBlock`. +/// This ensures compile-time type safety for expression-based constructs. +@resultBuilder +public enum ExprCodeBlockBuilder { + /// Builds a single expression code block from the provided expression. + /// - Parameter expression: The expression code block to build. + /// - Returns: The expression code block unchanged. + public static func buildBlock(_ expression: any ExprCodeBlock) -> any ExprCodeBlock { + expression + } + + /// Builds an expression code block from a single expression. + /// - Parameter expression: The expression code block to build. + /// - Returns: The expression code block unchanged. + public static func buildExpression(_ expression: any ExprCodeBlock) -> any ExprCodeBlock { + expression + } + + /// Builds an expression code block from the first branch of a conditional. + /// - Parameter first: The expression code block from the first branch. + /// - Returns: The expression code block from the first branch. + public static func buildEither(first: any ExprCodeBlock) -> any ExprCodeBlock { + first + } + + /// Builds an expression code block from the second branch of a conditional. + /// - Parameter second: The expression code block from the second branch. + /// - Returns: The expression code block from the second branch. + public static func buildEither(second: any ExprCodeBlock) -> any ExprCodeBlock { + second + } +} diff --git a/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift b/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift new file mode 100644 index 0000000..283a065 --- /dev/null +++ b/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift @@ -0,0 +1,71 @@ +// +// PatternConvertibleBuilder.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SwiftSyntax + +/// A result builder that produces exactly one `CodeBlock & PatternConvertible`. +/// This ensures compile-time type safety for pattern-based constructs. +@resultBuilder +public enum PatternConvertibleBuilder { + /// Builds a single pattern convertible code block from the provided pattern. + /// - Parameter pattern: The pattern convertible code block to build. + /// - Returns: The pattern convertible code block unchanged. + public static func buildBlock(_ pattern: any CodeBlock & PatternConvertible) -> any CodeBlock + & PatternConvertible + { + pattern + } + + /// Builds a pattern convertible code block from a single pattern. + /// - Parameter pattern: The pattern convertible code block to build. + /// - Returns: The pattern convertible code block unchanged. + public static func buildExpression(_ pattern: any CodeBlock & PatternConvertible) -> any CodeBlock + & PatternConvertible + { + pattern + } + + /// Builds a pattern convertible code block from the first branch of a conditional. + /// - Parameter first: The pattern convertible code block from the first branch. + /// - Returns: The pattern convertible code block from the first branch. + public static func buildEither(first: any CodeBlock & PatternConvertible) -> any CodeBlock + & PatternConvertible + { + first + } + + /// Builds a pattern convertible code block from the second branch of a conditional. + /// - Parameter second: The pattern convertible code block from the second branch. + /// - Returns: The pattern convertible code block from the second branch. + public static func buildEither(second: any CodeBlock & PatternConvertible) -> any CodeBlock + & PatternConvertible + { + second + } +} diff --git a/Sources/SyntaxKit/Declarations/Class.swift b/Sources/SyntaxKit/Declarations/Class.swift index 56446f3..f38ae5e 100644 --- a/Sources/SyntaxKit/Declarations/Class.swift +++ b/Sources/SyntaxKit/Declarations/Class.swift @@ -38,13 +38,14 @@ public struct Class: CodeBlock { private var isFinal: Bool = false private var attributes: [AttributeInfo] = [] - /// Creates a `class` declaration. + /// Creates a class declaration. /// - Parameters: /// - name: The name of the class. - /// - content: A ``CodeBlockBuilder`` that provides the members of the class. - public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + /// - content: A ``CodeBlockBuilder`` that provides the body of the class. + public init(_ name: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows + { self.name = name - self.members = content() + self.members = try content() } /// Sets the generic parameters for the class. diff --git a/Sources/SyntaxKit/Declarations/Enum.swift b/Sources/SyntaxKit/Declarations/Enum.swift index 1945142..a8e82c8 100644 --- a/Sources/SyntaxKit/Declarations/Enum.swift +++ b/Sources/SyntaxKit/Declarations/Enum.swift @@ -36,13 +36,14 @@ public struct Enum: CodeBlock { private var inheritance: [String] = [] private var attributes: [AttributeInfo] = [] - /// Creates an `enum` declaration. + /// Creates an enum declaration. /// - Parameters: /// - name: The name of the enum. - /// - content: A ``CodeBlockBuilder`` that provides the members of the enum. - public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + /// - content: A ``CodeBlockBuilder`` that provides the body of the enum. + public init(_ name: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows + { self.name = name - self.members = content() + self.members = try content() } /// Sets the inheritance for the enum. diff --git a/Sources/SyntaxKit/Declarations/Extension.swift b/Sources/SyntaxKit/Declarations/Extension.swift index af53db4..1ff7deb 100644 --- a/Sources/SyntaxKit/Declarations/Extension.swift +++ b/Sources/SyntaxKit/Declarations/Extension.swift @@ -39,10 +39,12 @@ public struct Extension: CodeBlock { /// Creates an extension declaration. /// - Parameters: /// - extendedType: The type being extended. - /// - content: A ``CodeBlockBuilder`` that provides the members of the extension. - public init(_ extendedType: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + /// - content: A ``CodeBlockBuilder`` that provides the body of the extension. + public init(_ extendedType: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) + rethrows + { self.extendedType = extendedType - self.members = content() + self.members = try content() } /// Sets one or more inherited protocols. diff --git a/Sources/SyntaxKit/Declarations/Import.swift b/Sources/SyntaxKit/Declarations/Import.swift index 191a037..37334d1 100644 --- a/Sources/SyntaxKit/Declarations/Import.swift +++ b/Sources/SyntaxKit/Declarations/Import.swift @@ -32,7 +32,7 @@ import SwiftSyntax /// A Swift `import` declaration. public struct Import: CodeBlock { private let moduleName: String - private var accessModifier: String? + private var accessModifier: AccessModifier? private var attributes: [AttributeInfo] = [] /// Creates an `import` declaration. @@ -42,9 +42,9 @@ public struct Import: CodeBlock { } /// Sets the access modifier for the import declaration. - /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Parameter access: The access modifier. /// - Returns: A copy of the import with the access modifier set. - public func access(_ access: String) -> Self { + public func access(_ access: AccessModifier) -> Self { var copy = self copy.accessModifier = access return copy @@ -65,21 +65,8 @@ public struct Import: CodeBlock { // Build access modifier var modifiers: DeclModifierListSyntax = [] if let access = accessModifier { - let keyword: Keyword - switch access { - case "public": - keyword = .public - case "private": - keyword = .private - case "internal": - keyword = .internal - case "fileprivate": - keyword = .fileprivate - default: - keyword = .public // fallback - } modifiers = DeclModifierListSyntax([ - DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + DeclModifierSyntax(name: .keyword(access.keyword, trailingTrivia: .space)) ]) } diff --git a/Sources/SyntaxKit/Declarations/Init.swift b/Sources/SyntaxKit/Declarations/Init.swift index b9b760d..400d38a 100644 --- a/Sources/SyntaxKit/Declarations/Init.swift +++ b/Sources/SyntaxKit/Declarations/Init.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// An initializer expression. -public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { +public struct Init: CodeBlock, ExprCodeBlock, LiteralValue, CodeBlockable { private let type: String private let parameters: [ParameterExp] @@ -45,9 +45,16 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue { /// - Parameters: /// - type: The type to initialize. /// - params: A ``ParameterExpBuilder`` that provides the parameters for the initializer. - public init(_ type: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) { + public init(_ type: String, @ParameterExpBuilderResult _ params: () throws -> [ParameterExp]) + rethrows + { self.type = type - self.parameters = params() + self.parameters = try params() + } + + /// The code block representation of this initializer expression. + public var codeBlock: CodeBlock { + self } public var exprSyntax: ExprSyntax { diff --git a/Sources/SyntaxKit/Declarations/Protocol.swift b/Sources/SyntaxKit/Declarations/Protocol.swift index 018af73..83d2db3 100644 --- a/Sources/SyntaxKit/Declarations/Protocol.swift +++ b/Sources/SyntaxKit/Declarations/Protocol.swift @@ -36,13 +36,14 @@ public struct Protocol: CodeBlock { private var inheritance: [String] = [] private var attributes: [AttributeInfo] = [] - /// Creates a `protocol` declaration. + /// Creates a protocol declaration. /// - Parameters: /// - name: The name of the protocol. - /// - content: A ``CodeBlockBuilder`` that provides the members of the protocol. - public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + /// - content: A ``CodeBlockBuilder`` that provides the body of the protocol. + public init(_ name: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows + { self.name = name - self.members = content() + self.members = try content() } /// Sets one or more inherited protocols. diff --git a/Sources/SyntaxKit/Declarations/Struct.swift b/Sources/SyntaxKit/Declarations/Struct.swift index 4b2dc56..82e9135 100644 --- a/Sources/SyntaxKit/Declarations/Struct.swift +++ b/Sources/SyntaxKit/Declarations/Struct.swift @@ -36,15 +36,16 @@ public struct Struct: CodeBlock { private var genericParameter: String? private var inheritance: [String] = [] private var attributes: [AttributeInfo] = [] - private var accessModifier: String? + private var accessModifier: AccessModifier? - /// Creates a `struct` declaration. + /// Creates a struct declaration. /// - Parameters: /// - name: The name of the struct. - /// - content: A ``CodeBlockBuilder`` that provides the members of the struct. - public init(_ name: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + /// - content: A ``CodeBlockBuilder`` that provides the body of the struct. + public init(_ name: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows + { self.name = name - self.members = content() + self.members = try content() } /// Sets the generic parameter for the struct. @@ -66,9 +67,9 @@ public struct Struct: CodeBlock { } /// Sets the access modifier for the struct declaration. - /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Parameter access: The access modifier. /// - Returns: A copy of the struct with the access modifier set. - public func access(_ access: String) -> Self { + public func access(_ access: AccessModifier) -> Self { var copy = self copy.accessModifier = access return copy @@ -142,21 +143,8 @@ public struct Struct: CodeBlock { // Build access modifier var modifiers: DeclModifierListSyntax = [] if let access = accessModifier { - let keyword: Keyword - switch access { - case "public": - keyword = .public - case "private": - keyword = .private - case "internal": - keyword = .internal - case "fileprivate": - keyword = .fileprivate - default: - keyword = .public // fallback - } modifiers = DeclModifierListSyntax([ - DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + DeclModifierSyntax(name: .keyword(access.keyword, trailingTrivia: .space)) ]) } diff --git a/Sources/SyntaxKit/ErrorHandling/Catch.swift b/Sources/SyntaxKit/ErrorHandling/Catch.swift index edad97f..4262002 100644 --- a/Sources/SyntaxKit/ErrorHandling/Catch.swift +++ b/Sources/SyntaxKit/ErrorHandling/Catch.swift @@ -65,6 +65,13 @@ public struct Catch: CodeBlock { Catch(enumCase, content) } + /// Creates a catch clause. + /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the catch clause. + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.pattern = nil + self.body = try content() + } + public var catchClauseSyntax: CatchClauseSyntax { // Build catch items (patterns) var catchItems: CatchItemListSyntax? diff --git a/Sources/SyntaxKit/Expressions/Assignment.swift b/Sources/SyntaxKit/Expressions/Assignment.swift index b3e26ac..7dda967 100644 --- a/Sources/SyntaxKit/Expressions/Assignment.swift +++ b/Sources/SyntaxKit/Expressions/Assignment.swift @@ -34,13 +34,16 @@ public struct Assignment: CodeBlock { private let target: String private let valueExpr: ExprSyntax + /// Creates an assignment where the value is an expression. + public init(_ target: String, _ value: any ExprCodeBlock) { + self.target = target + self.valueExpr = value.exprSyntax + } + /// Creates an assignment where the value is a literal. public init(_ target: String, _ literal: Literal) { self.target = target - guard let expr = literal.syntax.as(ExprSyntax.self) else { - fatalError("Literal.syntax did not produce ExprSyntax") - } - self.valueExpr = expr + self.valueExpr = literal.exprSyntax } /// Creates an assignment with an integer literal value. diff --git a/Sources/SyntaxKit/Expressions/Call.swift b/Sources/SyntaxKit/Expressions/Call.swift index a72843f..8154697 100644 --- a/Sources/SyntaxKit/Expressions/Call.swift +++ b/Sources/SyntaxKit/Expressions/Call.swift @@ -47,9 +47,11 @@ public struct Call: CodeBlock { /// - Parameters: /// - functionName: The name of the function to call. /// - params: A ``ParameterExpBuilder`` that provides the parameters for the function call. - public init(_ functionName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) { + public init( + _ functionName: String, @ParameterExpBuilderResult _ params: () throws -> [ParameterExp] + ) rethrows { self.functionName = functionName - self.parameters = params() + self.parameters = try params() } /// Marks this function call as throwing. @@ -71,7 +73,7 @@ public struct Call: CodeBlock { public var syntax: SyntaxProtocol { let function = TokenSyntax.identifier(functionName) let args = LabeledExprListSyntax( - parameters.enumerated().map { index, param in + parameters.enumerated().compactMap { index, param in let expr = param.syntax if let labeled = expr as? LabeledExprSyntax { var element = labeled @@ -92,7 +94,7 @@ public struct Call: CodeBlock { : nil ) } else { - fatalError("ParameterExp.syntax must return LabeledExprSyntax or ExprSyntax") + return nil } } ) diff --git a/Sources/SyntaxKit/Expressions/Closure+Capture.swift b/Sources/SyntaxKit/Expressions/Closure+Capture.swift index 87fd215..864ec10 100644 --- a/Sources/SyntaxKit/Expressions/Closure+Capture.swift +++ b/Sources/SyntaxKit/Expressions/Closure+Capture.swift @@ -43,15 +43,7 @@ private struct CaptureInfo { } private init(fromReference refExp: ReferenceExp) { - let keyword: Keyword - switch refExp.captureReferenceType.lowercased() { - case "weak": - keyword = .weak - case "unowned": - keyword = .unowned - default: - keyword = .weak // fallback to weak - } + let keyword = refExp.captureReferenceType.keyword self.specifier = ClosureCaptureSpecifierSyntax( specifier: .keyword(keyword, trailingTrivia: .space) @@ -61,6 +53,9 @@ private struct CaptureInfo { self.name = .identifier(varExp.name) } else { self.name = .identifier("self") // fallback + #warning( + "TODO: Review fallback for non-VariableExp capture expression - consider if this should be an error instead" + ) } } @@ -71,6 +66,9 @@ private struct CaptureInfo { self.name = .identifier(varExp.name) } else { self.name = .identifier("self") // fallback + #warning( + "TODO: Review fallback for non-VariableExp parameter value - consider if this should be an error instead" + ) } } } diff --git a/Sources/SyntaxKit/Expressions/Closure.swift b/Sources/SyntaxKit/Expressions/Closure.swift index 59be944..e5b3ee8 100644 --- a/Sources/SyntaxKit/Expressions/Closure.swift +++ b/Sources/SyntaxKit/Expressions/Closure.swift @@ -41,16 +41,133 @@ public struct Closure: CodeBlock { !parameters.isEmpty || returnType != nil || !capture.isEmpty || !attributes.isEmpty } + /// Creates a closure with all parameters. + /// - Parameters: + /// - capture: A ``ParameterExpBuilder`` that provides the capture list. + /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - returnType: The return type of the closure. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( - @ParameterExpBuilderResult capture: () -> [ParameterExp] = { [] }, - @ClosureParameterBuilderResult parameters: () -> [ClosureParameter] = { [] }, - returns returnType: String? = nil, - @CodeBlockBuilderResult body: () -> [CodeBlock] - ) { + @ParameterExpBuilderResult capture: () -> [ParameterExp], + @ClosureParameterBuilderResult parameters: () -> [ClosureParameter], + returns returnType: String?, + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { self.capture = capture() self.parameters = parameters() self.returnType = returnType - self.body = body() + self.body = try body() + } + + /// Creates a closure without a return type. + /// - Parameters: + /// - capture: A ``ParameterExpBuilder`` that provides the capture list. + /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + @ParameterExpBuilderResult capture: () -> [ParameterExp], + @ClosureParameterBuilderResult parameters: () -> [ClosureParameter], + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init(capture: capture, parameters: parameters, returns: nil, body: body) + } + + /// Creates a closure without parameters. + /// - Parameters: + /// - capture: A ``ParameterExpBuilder`` that provides the capture list. + /// - returnType: The return type of the closure. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + @ParameterExpBuilderResult capture: () -> [ParameterExp], + returns returnType: String?, + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init( + capture: capture, + parameters: [ClosureParameter].init, + returns: returnType, + body: body + ) + } + + /// Creates a closure without parameters and return type. + /// - Parameters: + /// - capture: A ``ParameterExpBuilder`` that provides the capture list. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + @ParameterExpBuilderResult capture: () -> [ParameterExp], + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init( + capture: capture, + parameters: [ClosureParameter].init, + returns: nil, + body: body + ) + } + + /// Creates a closure without capture list and return type. + /// - Parameters: + /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + @ClosureParameterBuilderResult parameters: () -> [ClosureParameter], + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init( + capture: [ParameterExp].init, + parameters: parameters, + returns: nil, + body: body + ) + } + + /// Creates a closure without capture list. + /// - Parameters: + /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - returnType: The return type of the closure. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + @ClosureParameterBuilderResult parameters: () -> [ClosureParameter], + returns returnType: String?, + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init( + capture: [ParameterExp].init, + parameters: parameters, + returns: returnType, + body: body + ) + } + + /// Creates a simple closure with only a body. + /// - Parameters: + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init( + capture: [ParameterExp].init, + parameters: [ClosureParameter].init, + returns: nil, + body: body + ) + } + + /// Creates a closure without capture list and parameters. + /// - Parameters: + /// - returnType: The return type of the closure. + /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. + public init( + returns returnType: String?, + @CodeBlockBuilderResult body: () throws -> [CodeBlock] + ) rethrows { + try self.init( + capture: [ParameterExp].init, + parameters: [ClosureParameter].init, + returns: returnType, + body: body + ) } public func attribute(_ attribute: String, arguments: [String] = []) -> Self { diff --git a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift index c720e7f..78753d5 100644 --- a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift +++ b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift @@ -94,7 +94,7 @@ public struct FunctionCallExp: CodeBlock { } let labeledArgs = LabeledExprListSyntax( - args.enumerated().map { index, param in + args.enumerated().compactMap { index, param in let expr = param.syntax if let labeled = expr as? LabeledExprSyntax { var element = labeled @@ -106,6 +106,8 @@ public struct FunctionCallExp: CodeBlock { } return element } else if let unlabeled = expr as? ExprSyntax { + // ParameterExp.syntax is guaranteed to return either LabeledExprSyntax or ExprSyntax + return LabeledExprSyntax( label: nil, colon: nil, @@ -115,12 +117,12 @@ public struct FunctionCallExp: CodeBlock { : nil ) } else { - fatalError("ParameterExp.syntax must return LabeledExprSyntax or ExprSyntax") + return nil } } ) - var functionCall = FunctionCallExprSyntax( + let functionCall = FunctionCallExprSyntax( calledExpression: ExprSyntax( MemberAccessExprSyntax( base: baseExpr, diff --git a/Sources/SyntaxKit/Expressions/Infix.swift b/Sources/SyntaxKit/Expressions/Infix.swift index 432f82f..261cf1f 100644 --- a/Sources/SyntaxKit/Expressions/Infix.swift +++ b/Sources/SyntaxKit/Expressions/Infix.swift @@ -30,28 +30,65 @@ import SwiftSyntax /// A generic binary (infix) operator expression, e.g. `a + b`. -public struct Infix: CodeBlock { +public struct Infix: CodeBlock, ExprCodeBlock { + public enum InfixError: Error, CustomStringConvertible { + case wrongOperandCount(expected: Int, got: Int) + case nonExprCodeBlockOperand + + public var description: String { + switch self { + case let .wrongOperandCount(expected, got): + return "Infix expects exactly \(expected) operands, got \(got)." + case .nonExprCodeBlockOperand: + return "Infix operands must conform to ExprCodeBlock protocol" + } + } + } + private let operation: String - private let operands: [CodeBlock] + private let leftOperand: any ExprCodeBlock + private let rightOperand: any ExprCodeBlock /// Creates an infix operator expression. /// - Parameters: /// - operation: The operator symbol as it should appear in source (e.g. "+", "-", "&&"). - /// - content: A ``CodeBlockBuilder`` that supplies the two operand expressions. + /// - lhs: The left-hand side expression that conforms to ExprCodeBlock. + /// - rhs: The right-hand side expression that conforms to ExprCodeBlock. + public init(_ operation: String, lhs: any ExprCodeBlock, rhs: any ExprCodeBlock) { + self.operation = operation + self.leftOperand = lhs + self.rightOperand = rhs + } + + /// Creates an infix operator expression with a builder closure. + /// - Parameters: + /// - operation: The operator symbol as it should appear in source (e.g. "+", "-", "&&"). + /// - content: A ``CodeBlockBuilder`` that supplies exactly two operand expressions. /// /// Exactly two operands must be supplied – a left-hand side and a right-hand side. - public init(_ operation: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) { + /// Each operand must conform to ExprCodeBlock. + @available(*, deprecated, message: "Use separate lhs and rhs parameters for compile-time safety") + public init(_ operation: String, @CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) + throws + { self.operation = operation - self.operands = content() - } + let operands = try content() - public var syntax: SyntaxProtocol { guard operands.count == 2 else { - fatalError("Infix expects exactly two operands, got \(operands.count).") + throw InfixError.wrongOperandCount(expected: 2, got: operands.count) } + guard let lhs = operands[0] as? any ExprCodeBlock, + let rhs = operands[1] as? any ExprCodeBlock + else { + throw InfixError.nonExprCodeBlockOperand + } + self.leftOperand = lhs + self.rightOperand = rhs + } - let left = operands[0].expr - let right = operands[1].expr + public var exprSyntax: ExprSyntax { + let left = leftOperand.exprSyntax + let right = rightOperand.exprSyntax let operatorExpr = ExprSyntax( BinaryOperatorExprSyntax( @@ -59,14 +96,20 @@ public struct Infix: CodeBlock { ) ) - return SequenceExprSyntax( - elements: ExprListSyntax([ - left, - operatorExpr, - right, - ]) + return ExprSyntax( + SequenceExprSyntax( + elements: ExprListSyntax([ + left, + operatorExpr, + right, + ]) + ) ) } + + public var syntax: SyntaxProtocol { + exprSyntax + } } // MARK: - Comparison Operators @@ -90,8 +133,9 @@ extension Infix { /// - operator: The comparison operator to use. /// - lhs: The left-hand side expression. /// - rhs: The right-hand side expression. - public init(_ operator: ComparisonOperator, lhs: CodeBlock, rhs: CodeBlock) { + public init(_ operator: ComparisonOperator, lhs: any ExprCodeBlock, rhs: any ExprCodeBlock) { self.operation = `operator`.symbol - self.operands = [lhs, rhs] + self.leftOperand = lhs + self.rightOperand = rhs } } diff --git a/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift b/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift index 39b85fc..24464d5 100644 --- a/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift +++ b/Sources/SyntaxKit/Expressions/Literal+PatternConvertible.swift @@ -32,9 +32,7 @@ import SwiftSyntax extension Literal: PatternConvertible { /// SwiftSyntax representation of the literal as a pattern. public var patternSyntax: PatternSyntax { - guard let expr = self.syntax.as(ExprSyntax.self) else { - fatalError("Literal.syntax did not return ExprSyntax") - } + let expr = self.exprSyntax return PatternSyntax(ExpressionPatternSyntax(expression: expr)) } } diff --git a/Sources/SyntaxKit/Expressions/Literal.swift b/Sources/SyntaxKit/Expressions/Literal.swift index 0a2dbee..96ae3bc 100644 --- a/Sources/SyntaxKit/Expressions/Literal.swift +++ b/Sources/SyntaxKit/Expressions/Literal.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A literal value. -public enum Literal: CodeBlock { +public enum Literal: CodeBlock, CodeBlockable { /// A string literal. case string(String) /// A floating-point literal. @@ -50,6 +50,11 @@ public enum Literal: CodeBlock { /// A dictionary literal. case dictionary([(Literal, Literal)]) + /// The code block representation of this literal. + public var codeBlock: CodeBlock { + self + } + /// The Swift type name for this literal. public var typeName: String { switch self { diff --git a/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift b/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift index 7b9e1c2..1297506 100644 --- a/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift +++ b/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// An expression that negates a property access. -public struct NegatedPropertyAccessExp: CodeBlock { +public struct NegatedPropertyAccessExp: CodeBlock, ExprCodeBlock { internal let base: CodeBlock /// Creates a negated property access expression. @@ -44,7 +44,7 @@ public struct NegatedPropertyAccessExp: CodeBlock { self.base = PropertyAccessExp(baseName: baseName, propertyName: propertyName) } - public var syntax: SyntaxProtocol { + public var exprSyntax: ExprSyntax { let memberAccess = base.syntax.as(ExprSyntax.self) ?? ExprSyntax( @@ -61,4 +61,8 @@ public struct NegatedPropertyAccessExp: CodeBlock { ) ) } + + public var syntax: SyntaxProtocol { + exprSyntax + } } diff --git a/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift b/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift index 433ebc4..36925a2 100644 --- a/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift +++ b/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift @@ -46,6 +46,9 @@ public struct OptionalChainingExp: CodeBlock { baseExpr = exprSyntax } else { // Fallback to a default expression if conversion fails + #warning( + "TODO: Review fallback for failed expression conversion - consider if this should be an error instead" + ) baseExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) } diff --git a/Sources/SyntaxKit/Expressions/PlusAssign.swift b/Sources/SyntaxKit/Expressions/PlusAssign.swift index 7c978e7..8572b81 100644 --- a/Sources/SyntaxKit/Expressions/PlusAssign.swift +++ b/Sources/SyntaxKit/Expressions/PlusAssign.swift @@ -34,13 +34,16 @@ public struct PlusAssign: CodeBlock { private let target: String private let valueExpr: ExprSyntax + /// Creates a `+=` expression with an expression value. + public init(_ target: String, _ value: any ExprCodeBlock) { + self.target = target + self.valueExpr = value.exprSyntax + } + /// Creates a `+=` expression with a literal value. public init(_ target: String, _ literal: Literal) { self.target = target - guard let expr = literal.syntax.as(ExprSyntax.self) else { - fatalError("Literal.syntax did not produce ExprSyntax") - } - self.valueExpr = expr + self.valueExpr = literal.exprSyntax } /// Creates a `+=` expression with an integer literal value. diff --git a/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift b/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift index a23b53f..ad0d488 100644 --- a/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift +++ b/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// An expression that accesses a property on a base expression. -public struct PropertyAccessExp: CodeBlock { +public struct PropertyAccessExp: CodeBlock, ExprCodeBlock { internal let base: CodeBlock internal let propertyName: String @@ -62,7 +62,7 @@ public struct PropertyAccessExp: CodeBlock { NegatedPropertyAccessExp(base: self) } - public var syntax: SyntaxProtocol { + public var exprSyntax: ExprSyntax { let baseSyntax = base.syntax.as(ExprSyntax.self) ?? ExprSyntax( @@ -77,4 +77,8 @@ public struct PropertyAccessExp: CodeBlock { ) ) } + + public var syntax: SyntaxProtocol { + exprSyntax + } } diff --git a/Sources/SyntaxKit/Expressions/ReferenceExp.swift b/Sources/SyntaxKit/Expressions/ReferenceExp.swift index 19b1c6b..ad017be 100644 --- a/Sources/SyntaxKit/Expressions/ReferenceExp.swift +++ b/Sources/SyntaxKit/Expressions/ReferenceExp.swift @@ -32,13 +32,13 @@ import SwiftSyntax /// A Swift reference expression (e.g., `weak self`, `unowned self`). public struct ReferenceExp: CodeBlock { private let base: CodeBlock - private let referenceType: String + private let referenceType: CaptureReferenceType /// Creates a reference expression. /// - Parameters: /// - base: The base expression to reference. - /// - referenceType: The type of reference (e.g., "weak", "unowned"). - public init(base: CodeBlock, referenceType: String) { + /// - referenceType: The type of reference. + public init(base: CodeBlock, referenceType: CaptureReferenceType) { self.base = base self.referenceType = referenceType } @@ -68,7 +68,7 @@ public struct ReferenceExp: CodeBlock { } /// Returns the reference type for use in capture lists - internal var captureReferenceType: String { + internal var captureReferenceType: CaptureReferenceType { referenceType } } diff --git a/Sources/SyntaxKit/Expressions/Return.swift b/Sources/SyntaxKit/Expressions/Return.swift index 78c05d4..c07447f 100644 --- a/Sources/SyntaxKit/Expressions/Return.swift +++ b/Sources/SyntaxKit/Expressions/Return.swift @@ -35,22 +35,43 @@ public struct Return: CodeBlock { /// Creates a `return` statement. /// - Parameter content: A ``CodeBlockBuilder`` that provides the expression to return. - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.exprs = content() + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.exprs = try content() } public var syntax: SyntaxProtocol { - guard let expr = exprs.first else { - fatalError("Return must have at least one expression.") - } - if let varExp = expr as? VariableExp { + if let expr = exprs.first { + if let varExp = expr as? VariableExp { + return ReturnStmtSyntax( + returnKeyword: .keyword(.return, trailingTrivia: .space), + expression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(varExp.name))) + ) + } + + // Try to get ExprSyntax from the expression + let exprSyntax: ExprSyntax + if let exprCodeBlock = expr as? ExprCodeBlock { + exprSyntax = exprCodeBlock.exprSyntax + } else if let syntax = expr.syntax.as(ExprSyntax.self) { + exprSyntax = syntax + } else { + // fallback: no valid expression + #warning( + "TODO: Review fallback for no valid expression - consider if this should be an error instead" + ) + return ReturnStmtSyntax( + returnKeyword: .keyword(.return, trailingTrivia: .space) + ) + } + return ReturnStmtSyntax( returnKeyword: .keyword(.return, trailingTrivia: .space), - expression: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(varExp.name))) + expression: exprSyntax + ) + } else { + // Bare return + return ReturnStmtSyntax( + returnKeyword: .keyword(.return, trailingTrivia: .space) ) } - return ReturnStmtSyntax( - returnKeyword: .keyword(.return, trailingTrivia: .space), - expression: ExprSyntax(expr.syntax) - ) } } diff --git a/Sources/SyntaxKit/Expressions/Task.swift b/Sources/SyntaxKit/Expressions/Task.swift index 56b1b32..9775b78 100644 --- a/Sources/SyntaxKit/Expressions/Task.swift +++ b/Sources/SyntaxKit/Expressions/Task.swift @@ -34,10 +34,10 @@ public struct Task: CodeBlock { private let body: [CodeBlock] private var attributes: [AttributeInfo] = [] - /// Creates a Task expression. - /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the task. - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.body = content() + /// Creates a Task block. + /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the Task. + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.body = try content() } /// Adds an attribute to the task. diff --git a/Sources/SyntaxKit/Functions/Function.swift b/Sources/SyntaxKit/Functions/Function.swift index 038eb09..0d1e798 100644 --- a/Sources/SyntaxKit/Functions/Function.swift +++ b/Sources/SyntaxKit/Functions/Function.swift @@ -48,12 +48,12 @@ public struct Function: CodeBlock { public init( _ name: String, returns returnType: String? = nil, - @CodeBlockBuilderResult _ content: () -> [CodeBlock] - ) { + @CodeBlockBuilderResult _ content: () throws -> [CodeBlock] + ) rethrows { self.name = name self.parameters = [] self.returnType = returnType - self.body = content() + self.body = try content() } /// Creates a `func` declaration. @@ -66,12 +66,12 @@ public struct Function: CodeBlock { _ name: String, returns returnType: String? = nil, @ParameterBuilderResult _ params: () -> [Parameter], - @CodeBlockBuilderResult _ content: () -> [CodeBlock] - ) { + @CodeBlockBuilderResult _ content: () throws -> [CodeBlock] + ) rethrows { self.name = name self.parameters = params() self.returnType = returnType - self.body = content() + self.body = try content() } /// Creates a `func` declaration with parameters and body using the DSL syntax. @@ -82,11 +82,11 @@ public struct Function: CodeBlock { public init( _ name: String, @ParameterBuilderResult _ params: () -> [Parameter], - @CodeBlockBuilderResult _ body: () -> [CodeBlock] - ) { + @CodeBlockBuilderResult _ body: () throws -> [CodeBlock] + ) rethrows { self.name = name self.parameters = params() self.returnType = nil - self.body = body() + self.body = try body() } } diff --git a/Sources/SyntaxKit/Parameters/ParameterExp.swift b/Sources/SyntaxKit/Parameters/ParameterExp.swift index 66c5876..2c09f87 100644 --- a/Sources/SyntaxKit/Parameters/ParameterExp.swift +++ b/Sources/SyntaxKit/Parameters/ParameterExp.swift @@ -47,6 +47,10 @@ public struct ParameterExp: CodeBlock { /// - Parameters: /// - name: The name of the parameter. /// - value: The string value of the parameter. + @available( + *, deprecated, + message: "Use ParameterExp(name:value:) with Literal.string() or VariableExp() instead" + ) public init(name: String, value: String) { self.name = name self.value = VariableExp(value) @@ -59,6 +63,10 @@ public struct ParameterExp: CodeBlock { } /// Convenience initializer for unlabeled parameter with a String value. + @available( + *, deprecated, + message: "Use ParameterExp(unlabeled:) with Literal.string() or VariableExp() instead" + ) public init(unlabeled value: String) { self.name = "" self.value = VariableExp(value) diff --git a/Sources/SyntaxKit/Utilities/Case.swift b/Sources/SyntaxKit/Utilities/Case.swift index 9f5eb7a..fc05929 100644 --- a/Sources/SyntaxKit/Utilities/Case.swift +++ b/Sources/SyntaxKit/Utilities/Case.swift @@ -37,14 +37,15 @@ public struct Case: CodeBlock { private let enumCaseName: String? private var associatedValue: (name: String, type: String)? - /// Creates a `case` for a `switch` statement. + /// Creates a case declaration. /// - Parameters: - /// - patterns: The patterns to match for the case. + /// - patterns: The patterns for the case. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. - public init(_ patterns: PatternConvertible..., @CodeBlockBuilderResult content: () -> [CodeBlock]) - { + public init( + _ patterns: PatternConvertible..., @CodeBlockBuilderResult content: () throws -> [CodeBlock] + ) rethrows { self.patterns = patterns - self.body = content() + self.body = try content() self.isEnumCase = false self.enumCaseName = nil self.associatedValue = nil diff --git a/Sources/SyntaxKit/Utilities/CodeBlockable.swift b/Sources/SyntaxKit/Utilities/CodeBlockable.swift new file mode 100644 index 0000000..c9a406b --- /dev/null +++ b/Sources/SyntaxKit/Utilities/CodeBlockable.swift @@ -0,0 +1,34 @@ +// +// CodeBlockable.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// Can export a `CodeBlock`. +public protocol CodeBlockable { + /// Returns a `CodeBlock`. + var codeBlock: CodeBlock { get } +} diff --git a/Sources/SyntaxKit/Utilities/Default.swift b/Sources/SyntaxKit/Utilities/Default.swift index 9ccb5b3..6ee3ca8 100644 --- a/Sources/SyntaxKit/Utilities/Default.swift +++ b/Sources/SyntaxKit/Utilities/Default.swift @@ -33,10 +33,10 @@ import SwiftSyntax public struct Default: CodeBlock { private let body: [CodeBlock] - /// Creates a `default` case for a `switch` statement. - /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the case. - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.body = content() + /// Creates a default case declaration. + /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the default case. + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.body = try content() } public var switchCaseSyntax: SwitchCaseSyntax { let statements = CodeBlockItemListSyntax( diff --git a/Sources/SyntaxKit/Utilities/Group.swift b/Sources/SyntaxKit/Utilities/Group.swift index 329574a..8edfd10 100644 --- a/Sources/SyntaxKit/Utilities/Group.swift +++ b/Sources/SyntaxKit/Utilities/Group.swift @@ -35,8 +35,8 @@ public struct Group: CodeBlock { /// Creates a group of code blocks. /// - Parameter content: A ``CodeBlockBuilder`` that provides the members of the group. - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.members = content() + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.members = try content() } public var syntax: SyntaxProtocol { @@ -53,7 +53,12 @@ public struct Group: CodeBlock { } else if let expr = block.syntax.as(ExprSyntax.self) { item = .expr(expr) } else { - fatalError("Unsupported syntax type in group: \(type(of: block.syntax)) from \(block)") + // Skip unsupported syntax types instead of crashing + // This allows the group to continue processing other valid blocks + #warning( + "TODO: Review fallback for unsupported syntax types - consider if this should be an error instead" + ) + return [] } return [CodeBlockItemSyntax(item: item, trailingTrivia: .newline)] } diff --git a/Sources/SyntaxKit/Utilities/Parenthesized.swift b/Sources/SyntaxKit/Utilities/Parenthesized.swift index be8959b..d7aa6f0 100644 --- a/Sources/SyntaxKit/Utilities/Parenthesized.swift +++ b/Sources/SyntaxKit/Utilities/Parenthesized.swift @@ -30,18 +30,18 @@ import SwiftSyntax /// A code block that wraps its content in parentheses. -public struct Parenthesized: CodeBlock { +public struct Parenthesized: CodeBlock, ExprCodeBlock { private let content: CodeBlock /// Creates a parenthesized code block. /// - Parameter content: The code block to wrap in parentheses. - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - let blocks = content() + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + let blocks = try content() precondition(blocks.count == 1, "Parenthesized expects exactly one code block.") self.content = blocks[0] } - public var syntax: SyntaxProtocol { + public var exprSyntax: ExprSyntax { ExprSyntax( TupleExprSyntax( leftParen: .leftParenToken(), @@ -52,4 +52,8 @@ public struct Parenthesized: CodeBlock { ) ) } + + public var syntax: SyntaxProtocol { + exprSyntax + } } diff --git a/Sources/SyntaxKit/Utilities/Then.swift b/Sources/SyntaxKit/Utilities/Then.swift index dd2fc2e..710d5b9 100644 --- a/Sources/SyntaxKit/Utilities/Then.swift +++ b/Sources/SyntaxKit/Utilities/Then.swift @@ -46,8 +46,10 @@ public struct Then: CodeBlock { /// The statements that make up the `else` body. public let body: [CodeBlock] - public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) { - self.body = content() + /// Creates a then block. + /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the then block. + public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { + self.body = try content() } public var syntax: SyntaxProtocol { diff --git a/Sources/SyntaxKit/Variables/ComputedProperty.swift b/Sources/SyntaxKit/Variables/ComputedProperty.swift index 7b6cdb6..fa963aa 100644 --- a/Sources/SyntaxKit/Variables/ComputedProperty.swift +++ b/Sources/SyntaxKit/Variables/ComputedProperty.swift @@ -34,7 +34,7 @@ public struct ComputedProperty: CodeBlock { private let name: String private let type: String private let body: [CodeBlock] - private var accessModifier: String? + private var accessModifier: AccessModifier? private let explicitType: Bool /// Creates a computed property declaration. @@ -47,18 +47,18 @@ public struct ComputedProperty: CodeBlock { _ name: String, type: String, explicitType: Bool = true, - @CodeBlockBuilderResult _ content: () -> [CodeBlock] - ) { + @CodeBlockBuilderResult _ content: () throws -> [CodeBlock] + ) rethrows { self.name = name self.type = type self.explicitType = explicitType - self.body = content() + self.body = try content() } /// Sets the access modifier for the computed property declaration. - /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Parameter access: The access modifier. /// - Returns: A copy of the computed property with the access modifier set. - public func access(_ access: String) -> Self { + public func access(_ access: AccessModifier) -> Self { var copy = self copy.accessModifier = access return copy @@ -96,21 +96,8 @@ public struct ComputedProperty: CodeBlock { // Build modifiers var modifiers: DeclModifierListSyntax = [] if let access = accessModifier { - let keyword: Keyword - switch access { - case "public": - keyword = .public - case "private": - keyword = .private - case "internal": - keyword = .internal - case "fileprivate": - keyword = .fileprivate - default: - keyword = .public // fallback - } modifiers = DeclModifierListSyntax([ - DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + DeclModifierSyntax(name: .keyword(access.keyword, trailingTrivia: .space)) ]) } diff --git a/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift b/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift index 1b4fc38..3b4224e 100644 --- a/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift +++ b/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift @@ -32,53 +32,23 @@ import Foundation // MARK: - Variable Literal Initializers extension Variable { - // swiftlint:disable cyclomatic_complexity /// Creates a `let` or `var` declaration with a literal value. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - equals: A literal value that conforms to ``LiteralValue``. - public init( + public init( _ kind: VariableKind, name: String, equals value: T ) { - let defaultValue: CodeBlock - if let literal = value as? Literal { - defaultValue = literal - } else if let tuple = value as? TupleLiteral { - defaultValue = Literal.tuple(tuple.elements) - } else if let array = value as? ArrayLiteral { - defaultValue = Literal.array(array.elements) - } else if let dict = value as? DictionaryLiteral { - defaultValue = Literal.dictionary(dict.elements) - } else if let array = value as? [String] { - defaultValue = Literal.array(array.map { .string($0) }) - } else if let dict = value as? [Int: String] { - defaultValue = Literal.dictionary(dict.map { (.integer($0.key), .string($0.value)) }) - } else if let dictExpr = value as? DictionaryExpr { - defaultValue = dictExpr - } else if let initExpr = value as? Init { - defaultValue = initExpr - } else if let codeBlock = value as? CodeBlock { - defaultValue = codeBlock - } else { - // For any other LiteralValue type that doesn't conform to CodeBlock, - // create a fallback or throw an error - fatalError( - "Variable: Unsupported LiteralValue type that doesn't conform to CodeBlock: \(T.self)" - ) - } - self.init( kind: kind, name: name, type: value.typeName, - defaultValue: defaultValue, + defaultValue: value.codeBlock, explicitType: false ) } - // swiftlint:enable cyclomatic_complexity - /// Creates a `let` or `var` declaration with a string literal value. /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. @@ -173,14 +143,14 @@ extension Variable { public init( _ kind: VariableKind, name: String, - @CodeBlockBuilderResult value: () -> [CodeBlock], + @CodeBlockBuilderResult value: () throws -> [CodeBlock], explicitType: Bool? = nil - ) { + ) rethrows { self.init( kind: kind, name: name, type: "", - defaultValue: value().first ?? EmptyCodeBlock(), + defaultValue: try value().first ?? EmptyCodeBlock(), explicitType: explicitType ?? false ) } diff --git a/Sources/SyntaxKit/Variables/Variable+Modifiers.swift b/Sources/SyntaxKit/Variables/Variable+Modifiers.swift index cdbf079..bfaf90d 100644 --- a/Sources/SyntaxKit/Variables/Variable+Modifiers.swift +++ b/Sources/SyntaxKit/Variables/Variable+Modifiers.swift @@ -60,21 +60,7 @@ extension Variable { } /// Builds an access modifier. - private func buildAccessModifier(_ access: String) -> DeclModifierSyntax { - let keyword: Keyword - switch access { - case "public": - keyword = .public - case "private": - keyword = .private - case "internal": - keyword = .internal - case "fileprivate": - keyword = .fileprivate - default: - keyword = .public // fallback - } - - return DeclModifierSyntax(name: .keyword(keyword, trailingTrivia: .space)) + private func buildAccessModifier(_ access: AccessModifier) -> DeclModifierSyntax { + DeclModifierSyntax(name: .keyword(access.keyword, trailingTrivia: .space)) } } diff --git a/Sources/SyntaxKit/Variables/Variable.swift b/Sources/SyntaxKit/Variables/Variable.swift index c0cda6a..ec2e133 100644 --- a/Sources/SyntaxKit/Variables/Variable.swift +++ b/Sources/SyntaxKit/Variables/Variable.swift @@ -40,7 +40,7 @@ public struct Variable: CodeBlock { internal var isAsync: Bool = false private var attributes: [AttributeInfo] = [] private var explicitType: Bool = false - internal var accessModifier: String? + internal var accessModifier: AccessModifier? /// Internal initializer used by extension initializers to reduce code duplication. /// - Parameters: @@ -86,9 +86,9 @@ public struct Variable: CodeBlock { } /// Sets the access modifier for the variable declaration. - /// - Parameter access: The access modifier (e.g., "public", "private"). + /// - Parameter access: The access modifier. /// - Returns: A copy of the variable with the access modifier set. - public func access(_ access: String) -> Self { + public func access(_ access: AccessModifier) -> Self { var copy = self copy.accessModifier = access return copy diff --git a/Sources/SyntaxKit/Variables/VariableExp.swift b/Sources/SyntaxKit/Variables/VariableExp.swift index 30d73c2..d8803b3 100644 --- a/Sources/SyntaxKit/Variables/VariableExp.swift +++ b/Sources/SyntaxKit/Variables/VariableExp.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// An expression that refers to a variable. -public struct VariableExp: CodeBlock, PatternConvertible { +public struct VariableExp: CodeBlock, PatternConvertible, ExprCodeBlock { internal let name: String /// Creates a variable expression. @@ -65,9 +65,9 @@ public struct VariableExp: CodeBlock, PatternConvertible { } /// Creates a reference to this variable. - /// - Parameter referenceType: The type of reference (e.g., "weak", "unowned"). + /// - Parameter referenceType: The type of reference. /// - Returns: A reference expression. - public func reference(_ referenceType: String) -> CodeBlock { + public func reference(_ referenceType: CaptureReferenceType) -> CodeBlock { ReferenceExp(base: self, referenceType: referenceType) } @@ -81,6 +81,10 @@ public struct VariableExp: CodeBlock, PatternConvertible { ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) } + public var exprSyntax: ExprSyntax { + ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) + } + public var patternSyntax: PatternSyntax { PatternSyntax(IdentifierPatternSyntax(identifier: .identifier(name))) } diff --git a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift index d8352c1..b312c83 100644 --- a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift @@ -9,7 +9,7 @@ import Testing // Build DSL equivalent of Examples/Remaining/concurrency/dsl.swift // Note: This test includes the Item struct that's referenced but not defined in the original DSL - let program = Group { + let program = try Group { // Item struct (needed for the vending machine) Struct("Item") { Variable(.let, name: "price", type: "Int").withExplicitType() @@ -25,7 +25,7 @@ import Testing .inherits("Error") // VendingMachine class - Class("VendingMachine") { + try Class("VendingMachine") { Variable( .var, name: "inventory", @@ -55,33 +55,35 @@ import Testing ) Variable(.var, name: "coinsDeposited", equals: 0) - Function("vend") { + try Function("vend") { Parameter("name", labeled: "itemNamed", type: "String") } _: { Guard { Let("item", "inventory[name]") } else: { - Throw(VariableExp("VendingMachineError.invalidSelection")) + Throw( + EnumCase("VendingMachineError.invalidSelection") + ) } - Guard { - Infix(">") { + try Guard { + try Infix(">") { VariableExp("item").property("count") Literal.integer(0) } } else: { - Throw(VariableExp("VendingMachineError.outOfStock")) + Throw(EnumCase("VendingMachineError.outOfStock")) } - Guard { - Infix("<=") { + try Guard { + try Infix("<=") { VariableExp("item").property("price") VariableExp("coinsDeposited") } } else: { Throw( - Call("VendingMachineError.insufficientFunds") { + try Call("VendingMachineError.insufficientFunds") { ParameterExp( name: "coinsNeeded", - value: Infix("-") { + value: try Infix("-") { VariableExp("item").property("price") VariableExp("coinsDeposited") } @@ -89,18 +91,18 @@ import Testing } ) } - Infix("-=") { + try Infix("-=") { VariableExp("coinsDeposited") VariableExp("item").property("price") } Variable(.var, name: "newItem", equals: Literal.ref("item")) - Infix("-=") { + try Infix("-=") { VariableExp("newItem").property("count") Literal.integer(1) } Assignment("inventory[name]", .ref("newItem")) Call("print") { - ParameterExp(unlabeled: "\"Dispensing \\(name)\"") + ParameterExp(unlabeled: Literal.string("Dispensing \\(name)")) } } .throws() diff --git a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift index f5170c6..47d0821 100644 --- a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift @@ -8,21 +8,21 @@ import Testing internal func testCompletedConditionalsExample() throws { // Build DSL equivalent of Examples/Completed/conditionals/dsl.swift - let program = Group { + let program = try Group { // MARK: Basic If Statements Variable(.let, name: "temperature", equals: 25) .comment { Line("Simple if statement") } - If { - Infix(">") { + try If { + try Infix(">") { VariableExp("temperature") Literal.integer(30) } } then: { Call("print") { - ParameterExp(name: "", value: "\"It's hot outside!\"") + ParameterExp(unlabeled: "\"It's hot outside!\"") } } @@ -32,41 +32,39 @@ import Testing Line("If-else statement") } - If { - Infix(">=") { + try If { + try Infix(">=") { VariableExp("score") Literal.integer(90) } } then: { Call("print") { - ParameterExp(name: "", value: "\"Excellent!\"") + ParameterExp(unlabeled: "\"Excellent!\"") } } else: { - If { - Infix(">=") { + try If { + try Infix(">=") { VariableExp("score") Literal.integer(80) } } then: { Call("print") { - ParameterExp(name: "", value: "\"Good job!\"") - } - } - - If { - Infix(">=") { - VariableExp("score") - Literal.integer(70) - } - } then: { - Call("print") { - ParameterExp(name: "", value: "\"Passing\"") + ParameterExp(unlabeled: "\"Good job!\"") } - } - - Then { - Call("print") { - ParameterExp(name: "", value: "\"Needs improvement\"") + } else: { + try If { + try Infix(">=") { + VariableExp("score") + Literal.integer(70) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "\"Passing\"") + } + } else: { + Call("print") { + ParameterExp(unlabeled: "\"Needs improvement\"") + } } } } @@ -118,7 +116,7 @@ import Testing } // MARK: - Guard Statements - Function( + try Function( "greet", { Parameter(name: "person", type: "[String: String]") @@ -275,12 +273,12 @@ import Testing Line("MARK: - Labeled Statements") Line("Using labeled statements with break") } - Variable(.var, name: "board") { - Init("[Int]") { + try Variable(.var, name: "board") { + try Init("[Int]") { ParameterExp(name: "repeating", value: Literal.integer(0)) ParameterExp( name: "count", - value: Infix("+") { + value: try Infix("+") { VariableExp("finalSquare") Literal.integer(1) } @@ -300,45 +298,45 @@ import Testing Variable(.var, name: "square", equals: Literal.integer(0)) Variable(.var, name: "diceRoll", equals: Literal.integer(0)) - While { - Infix("!=") { + try While( + try Infix("!=") { VariableExp("square") VariableExp("finalSquare") } - } then: { + ) { PlusAssign("diceRoll", 1) - If { - Infix("==") { + try If { + try Infix("==") { VariableExp("diceRoll") Literal.integer(7) } } then: { Assignment("diceRoll", 1) } - Switch( - Infix("+") { + try Switch( + try Infix("+") { VariableExp("square") VariableExp("diceRoll") } ) { - SwitchCase(VariableExp("finalSquare")) { + SwitchCase("finalSquare") { Break() } - SwitchCase { + try SwitchCase { SwitchLet("newSquare") - Infix(">") { + try Infix(">") { VariableExp("newSquare") VariableExp("finalSquare") } } content: { Continue() } - Default { - Infix("+=") { + try Default { + try Infix("+=") { VariableExp("square") VariableExp("diceRoll") } - Infix("+=") { + try Infix("+=") { VariableExp("square") VariableExp("board[square]") } @@ -498,4 +496,56 @@ import Testing #expect(generated == expected) } + + @Test("Conditionals example generates correct syntax") + internal func testConditionalsExample() throws { + _ = try If { + try Infix(">") { + VariableExp("temperature") + Literal.integer(30) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "It's hot!") + } + } else: { + try If { + try Infix(">=") { + VariableExp("score") + Literal.integer(90) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "Excellent!") + } + } else: { + try If { + try Infix(">=") { + VariableExp("score") + Literal.integer(80) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "Good!") + } + } else: { + try If { + try Infix(">=") { + VariableExp("score") + Literal.integer(70) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "Pass") + } + } else: { + Call("print") { + ParameterExp(unlabeled: "Fail") + } + } + } + } + } + // ... rest of the test ... + } } diff --git a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift index 3c8aabb..c510e0d 100644 --- a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift @@ -8,7 +8,7 @@ import Testing internal func testCompletedForLoopsExample() throws { // Build DSL equivalent of Examples/Completed/for_loops/dsl.swift - let program = Group { + let program = try Group { // MARK: - Basic For-in Loop Variable( .let, @@ -80,12 +80,12 @@ import Testing ]) ) - For( + try For( VariableExp("number"), in: VariableExp("numbers"), where: { - Infix("==") { - Infix("%") { + try Infix("==") { + try Infix("%") { VariableExp("number") Literal.integer(2) } diff --git a/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift b/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift index 9edf180..05806bd 100644 --- a/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift @@ -37,7 +37,7 @@ import Testing internal func testSwiftUIExample() throws { // Test the onToggle variable with closure type and attributes let onToggleVariable = Variable(.let, name: "onToggle", type: "(Date) -> Void") - .access("private") + .access(.private) let generatedCode = onToggleVariable.generateCode() #expect(generatedCode.contains("private let onToggle")) @@ -68,10 +68,10 @@ import Testing internal func testSwiftUITodoItemRowExample() throws { // Use the full DSL from Examples/Completed/swiftui/dsl.swift let dsl = Group { - Import("SwiftUI").access("public") + Import("SwiftUI").access(.public) Struct("TodoItemRow") { - Variable(.let, name: "item", type: "TodoItem").access("private") + Variable(.let, name: "item", type: "TodoItem").access(.private) Variable( .let, @@ -83,7 +83,7 @@ import Testing .attribute("MainActor") .attribute("Sendable") ) - .access("private") + .access(.private) ComputedProperty("body", type: "some View") { Init("HStack") { @@ -124,7 +124,7 @@ import Testing ParameterExp( unlabeled: Closure( capture: { - ParameterExp(unlabeled: VariableExp("self").reference("weak")) + ParameterExp(unlabeled: VariableExp("self").reference(.weak)) }, body: { VariableExp("self").optional().call("onToggle") { @@ -151,10 +151,10 @@ import Testing ) } } - .access("public") + .access(.public) } .inherits("View") - .access("public") + .access(.public) } // Expected Swift code from Examples/Completed/swiftui/code.swift diff --git a/Tests/SyntaxKitTests/Unit/ControlFlow/ConditionalsTests.swift b/Tests/SyntaxKitTests/Unit/ControlFlow/ConditionalsTests.swift index f2f87f6..a442096 100644 --- a/Tests/SyntaxKitTests/Unit/ControlFlow/ConditionalsTests.swift +++ b/Tests/SyntaxKitTests/Unit/ControlFlow/ConditionalsTests.swift @@ -6,11 +6,11 @@ import Testing @Test("If / else-if / else chain generates correct syntax") internal func testIfElseChain() throws { // Arrange: build the DSL example using the updated APIs - let conditional = Group { + let conditional = try Group { Variable(.let, name: "score", type: "Int", equals: "85") - If { - Infix(">=") { + try If { + try Infix(">=") { VariableExp("score") Literal.integer(90) } @@ -19,8 +19,8 @@ import Testing ParameterExp(name: "", value: "\"Excellent!\"") } } else: { - If { - Infix(">=") { + try If { + try Infix(">=") { VariableExp("score") Literal.integer(80) } @@ -47,4 +47,32 @@ import Testing #expect(generated.contains("else if score >= 80".normalize())) #expect(generated.contains("else {".normalize())) } + + @Test("If with multiple conditions generates correct syntax") + internal func testIfWithMultipleConditions() throws { + let ifStatement = try If { + try Infix(">=") { + VariableExp("score") + Literal.integer(90) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "Excellent!") + } + } else: { + try If { + try Infix(">=") { + VariableExp("score") + Literal.integer(80) + } + } then: { + Call("print") { + ParameterExp(unlabeled: "Good!") + } + } + } + let generated = ifStatement.generateCode() + #expect(generated.contains("if score >= 90")) + #expect(generated.contains("else if score >= 80")) + } } diff --git a/Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift b/Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift index 3b922cf..1cd25fd 100644 --- a/Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift +++ b/Tests/SyntaxKitTests/Unit/ControlFlow/ForLoopTests.swift @@ -5,7 +5,7 @@ import Testing @Suite internal final class ForLoopTests { @Test - internal func testSimpleForInLoop() { + internal func testSimpleForInLoop() throws { let forLoop = For( VariableExp("item"), in: VariableExp("items"), @@ -22,12 +22,12 @@ internal final class ForLoopTests { } @Test - internal func testForInWithWhereClause() { - let forLoop = For( + internal func testForInWithWhereClause() throws { + let forLoop = try For( VariableExp("number"), in: VariableExp("numbers"), where: { - Infix("%") { + try Infix("%") { VariableExp("number") Literal.integer(2) } diff --git a/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTests.swift b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTests.swift index c4a5720..8e570df 100644 --- a/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTests.swift +++ b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTests.swift @@ -5,31 +5,119 @@ import Testing internal struct EdgeCaseTests { // MARK: - Error Handling Tests - @Test("Infix with wrong number of operands throws fatal error") - internal func testInfixWrongOperandCount() { - // This test documents the expected behavior - // In a real scenario, this would cause a fatal error - // We can't easily test fatalError in unit tests, but we can document it - let infix = Infix("+") { - // Only one operand - should cause fatal error - VariableExp("x") + @Test("Infix with wrong number of operands throws error") + internal func testInfixWrongOperandCount() throws { + // Test that Infix throws an error when given wrong number of operands + do { + _ = try Infix("+") { + // Only one operand - should throw error + VariableExp("x") + } + // If we reach here, no error was thrown, which is unexpected + #expect(false, "Expected error to be thrown for wrong operand count") + } catch let error as Infix.InfixError { + // Verify it's the correct error type + switch error { + case let .wrongOperandCount(expected, got): + #expect(expected == 2) + #expect(got == 1) + case .nonExprCodeBlockOperand: + #expect(false, "Expected wrongOperandCount error, got nonExprCodeBlockOperand") + } + } catch { + #expect(false, "Expected InfixError, got \(type(of: error))") } + } + + // MARK: - Default Condition Tests + + @Test("If with no conditions uses true as default") + internal func testIfWithNoConditionsUsesTrueAsDefault() throws { + let ifStatement = If { + Return { + Literal.string("executed") + } + } + + let generated = ifStatement.generateCode() + #expect(generated.contains("if true")) + #expect(generated.contains("return \"executed\"")) + } - // The fatal error would occur when accessing .syntax - // This test documents the expected behavior - #expect(true) // Placeholder - fatal errors can't be easily tested + @Test("Guard with no conditions uses true as default") + internal func testGuardWithNoConditionsUsesTrueAsDefault() throws { + let guardStatement = Guard { + Return { + Literal.string("executed") + } + } + + let generated = guardStatement.generateCode() + #expect(generated.contains("guard true")) + #expect(generated.contains("return \"executed\"")) } - @Test("Return with no expressions throws fatal error") + // MARK: - Return Statement Tests + + @Test("Return with expression generates correct syntax") + internal func testReturnWithExpression() { + let returnStatement = Return { + Literal.string("hello") + } + + let generated = returnStatement.generateCode() + #expect(generated.contains("return \"hello\"")) + } + + @Test("Return with variable expression generates correct syntax") + internal func testReturnWithVariableExpression() { + let returnStatement = Return { + VariableExp("value") + } + + let generated = returnStatement.generateCode() + #expect(generated.contains("return value")) + } + + @Test("Return with no expressions generates bare return") internal func testReturnWithNoExpressions() { - // This test documents the expected behavior - // In a real scenario, this would cause a fatal error - let returnStmt = Return { - // Empty - should cause fatal error + let returnStatement = Return { + // Empty - should generate bare return } - // The fatal error would occur when accessing .syntax - // This test documents the expected behavior - #expect(true) // Placeholder - fatal errors can't be easily tested + let generated = returnStatement.generateCode() + #expect(generated.contains("return")) + #expect(!generated.contains("return ")) + #expect(!generated.contains("return \"\"")) + #expect(!generated.contains("return nil")) + } + + // MARK: - TupleAssignment Tests + + @Test("TupleAssignment asyncSet falls back to regular syntax when conditions not met") + internal func testTupleAssignmentAsyncSetFallback() { + // Test case 1: Value is not a Tuple + let tupleAssignment1 = TupleAssignment( + ["a", "b"], + equals: Literal.string("not a tuple") + ).asyncSet() + + let generated1 = tupleAssignment1.generateCode() + #expect(generated1.contains("let (a, b) = \"not a tuple\"")) + #expect(!generated1.contains("async let")) + + // Test case 2: Element count mismatch + let tupleAssignment2 = TupleAssignment( + ["a", "b", "c"], // 3 elements + equals: Tuple { + Literal.integer(1) + Literal.integer(2) + // Missing third element + } + ).asyncSet() + + let generated2 = tupleAssignment2.generateCode() + #expect(generated2.contains("let (a, b, c) = (1, 2)")) + #expect(!generated2.contains("async let")) } } diff --git a/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsExpressions.swift b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsExpressions.swift index 8296755..659e43d 100644 --- a/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsExpressions.swift +++ b/Tests/SyntaxKitTests/Unit/EdgeCases/EdgeCaseTestsExpressions.swift @@ -36,15 +36,15 @@ internal struct EdgeCaseTestsExpressions { @Test("Infix with complex expressions generates correct syntax") internal func testInfixWithComplexExpressions() throws { - let infix = Infix("*") { - Parenthesized { - Infix("+") { + let infix = try Infix("*") { + try Parenthesized { + try Infix("+") { VariableExp("a") VariableExp("b") } } - Parenthesized { - Infix("-") { + try Parenthesized { + try Infix("-") { VariableExp("c") VariableExp("d") } @@ -67,8 +67,8 @@ internal struct EdgeCaseTestsExpressions { @Test("Return with complex expression generates correct syntax") internal func testReturnWithComplexExpression() throws { - let returnStmt = Return { - Infix("+") { + let returnStmt = try Return { + try Infix("+") { VariableExp("a") VariableExp("b") } diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift index d913c4d..98c5376 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/ClosureCaptureCoverageTests.swift @@ -39,34 +39,12 @@ import Testing internal final class ClosureCaptureCoverageTests { // MARK: - Closure+Capture.swift Coverage Tests - /// Tests fallback cases in CaptureInfo initializers. - @Test("Capture info fallback cases") - internal func testCaptureInfoFallbackCases() { - // Test fallback cases in CaptureInfo initializers - - // Test with unknown reference type (should fallback to weak) - let unknownRef = ReferenceExp(base: VariableExp("self"), referenceType: "unknown") - let paramWithUnknownRef = ParameterExp(name: "self", value: unknownRef) - let closure = Closure( - capture: { paramWithUnknownRef }, - body: { - Variable(.let, name: "result", equals: "value") - } - ) - - let syntax = closure.syntax - let description = syntax.description - - // Should fallback to weak - #expect(description.contains("[weak self]")) - } - /// Tests CaptureInfo with non-VariableExp capture expression. @Test("Capture info with non VariableExp") internal func testCaptureInfoWithNonVariableExp() { // Test CaptureInfo with non-VariableExp capture expression let initBlock = Init("String") - let ref = ReferenceExp(base: initBlock, referenceType: "weak") + let ref = ReferenceExp(base: initBlock, referenceType: .weak) let param = ParameterExp(name: "self", value: ref) let closure = Closure( capture: { param }, diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift index 6129335..2f7a95b 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpBasicTests.swift @@ -42,14 +42,14 @@ internal final class ReferenceExpBasicTests { internal func testBasicWeakReference() { let reference = ReferenceExp( base: VariableExp("self"), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("self")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests basic unowned reference expression. @@ -57,14 +57,14 @@ internal final class ReferenceExpBasicTests { internal func testBasicUnownedReference() { let reference = ReferenceExp( base: VariableExp("self"), - referenceType: "unowned" + referenceType: .unowned ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("self")) - #expect(reference.captureReferenceType == "unowned") + #expect(reference.captureReferenceType == .unowned) } /// Tests reference expression with variable base. @@ -72,26 +72,24 @@ internal final class ReferenceExpBasicTests { internal func testReferenceWithVariableBase() { let reference = ReferenceExp( base: VariableExp("delegate"), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("delegate")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with different reference types. @Test("Reference expression with different reference types generates correct syntax") internal func testReferenceWithDifferentReferenceTypes() { - let weakRef = ReferenceExp(base: VariableExp("self"), referenceType: "weak") - let unownedRef = ReferenceExp(base: VariableExp("self"), referenceType: "unowned") - let strongRef = ReferenceExp(base: VariableExp("self"), referenceType: "strong") + let weakRef = ReferenceExp(base: VariableExp("self"), referenceType: .weak) + let unownedRef = ReferenceExp(base: VariableExp("self"), referenceType: .unowned) - #expect(weakRef.captureReferenceType == "weak") - #expect(unownedRef.captureReferenceType == "unowned") - #expect(strongRef.captureReferenceType == "strong") + #expect(weakRef.captureReferenceType == .weak) + #expect(unownedRef.captureReferenceType == .unowned) } /// Tests capture expression property access. @@ -100,7 +98,7 @@ internal final class ReferenceExpBasicTests { let base = VariableExp("self") let reference = ReferenceExp( base: base, - referenceType: "weak" + referenceType: .weak ) #expect(reference.captureExpression.syntax.description == base.syntax.description) @@ -111,39 +109,9 @@ internal final class ReferenceExpBasicTests { internal func testCaptureReferenceTypePropertyAccess() { let reference = ReferenceExp( base: VariableExp("self"), - referenceType: "unowned" + referenceType: .unowned ) - #expect(reference.captureReferenceType == "unowned") - } - - /// Tests reference expression with empty string reference type. - @Test("Reference expression with empty string reference type generates correct syntax") - internal func testReferenceWithEmptyStringReferenceType() { - let reference = ReferenceExp( - base: VariableExp("self"), - referenceType: "" - ) - - let syntax = reference.syntax - let description = syntax.description - - #expect(description.contains("self")) - #expect(reference.captureReferenceType.isEmpty) - } - - /// Tests reference expression with custom reference type. - @Test("Reference expression with custom reference type generates correct syntax") - internal func testReferenceWithCustomReferenceType() { - let reference = ReferenceExp( - base: VariableExp("self"), - referenceType: "custom" - ) - - let syntax = reference.syntax - let description = syntax.description - - #expect(description.contains("self")) - #expect(reference.captureReferenceType == "custom") + #expect(reference.captureReferenceType == .unowned) } } diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift index ac4b1ad..ea754db 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpComplexTests.swift @@ -48,14 +48,14 @@ internal final class ReferenceExpComplexTests { let reference = ReferenceExp( base: conditional, - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("isEnabled ? enabledValue : disabledValue")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with closure base. @@ -64,14 +64,14 @@ internal final class ReferenceExpComplexTests { let closure = Closure(body: { VariableExp("result") }) let reference = ReferenceExp( base: closure, - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description.normalize() #expect(description.contains("{ result }".normalize())) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with enum case base. @@ -80,13 +80,13 @@ internal final class ReferenceExpComplexTests { let enumCase = EnumCase("active") let reference = ReferenceExp( base: enumCase, - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description.normalize() #expect(description.contains(".active".normalize())) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } } diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift index 5eb42ed..c1f162a 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpFunctionTests.swift @@ -42,14 +42,14 @@ internal final class ReferenceExpFunctionTests { internal func testReferenceWithFunctionCallBase() { let reference = ReferenceExp( base: Call("getCurrentUser"), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("getCurrentUser()")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with method call base. @@ -57,14 +57,14 @@ internal final class ReferenceExpFunctionTests { internal func testReferenceWithMethodCallBase() { let reference = ReferenceExp( base: Call("getData"), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("getData()")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with init call base. @@ -73,13 +73,13 @@ internal final class ReferenceExpFunctionTests { let initCall = Init("String") let reference = ReferenceExp( base: initCall, - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("String()")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } } diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift index 156a5f5..831379e 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpLiteralTests.swift @@ -42,14 +42,14 @@ internal final class ReferenceExpLiteralTests { internal func testReferenceWithLiteralBase() { let reference = ReferenceExp( base: Literal.ref("constant"), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("constant")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with array literal base. @@ -57,14 +57,14 @@ internal final class ReferenceExpLiteralTests { internal func testReferenceWithArrayLiteralBase() { let reference = ReferenceExp( base: Literal.array([Literal.string("item1"), Literal.string("item2")]), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("[\"item1\", \"item2\"]")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with dictionary literal base. @@ -72,14 +72,14 @@ internal final class ReferenceExpLiteralTests { internal func testReferenceWithDictionaryLiteralBase() { let reference = ReferenceExp( base: Literal.dictionary([(Literal.string("key"), Literal.string("value"))]), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description.replacingOccurrences(of: " ", with: "") #expect(description.contains("[\"key\":\"value\"]".replacingOccurrences(of: " ", with: ""))) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with tuple literal base. @@ -87,13 +87,13 @@ internal final class ReferenceExpLiteralTests { internal func testReferenceWithTupleLiteralBase() { let reference = ReferenceExp( base: Literal.tuple([Literal.string("first"), Literal.string("second")]), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("(\"first\", \"second\")")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } } diff --git a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift index 8da4632..f720efa 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/ReferenceExp/ReferenceExpPropertyTests.swift @@ -42,14 +42,14 @@ internal final class ReferenceExpPropertyTests { internal func testReferenceWithPropertyAccessBase() { let reference = ReferenceExp( base: PropertyAccessExp(base: VariableExp("viewController"), propertyName: "delegate"), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("viewController.delegate")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with nested property access base. @@ -60,14 +60,14 @@ internal final class ReferenceExpPropertyTests { base: PropertyAccessExp(base: VariableExp("user"), propertyName: "profile"), propertyName: "settings" ), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("user.profile.settings")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with complex base expression. @@ -78,14 +78,14 @@ internal final class ReferenceExpPropertyTests { base: Call("getUserManager"), propertyName: "currentUser" ), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("getUserManager().currentUser")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } /// Tests reference expression with complex nested expression base. @@ -96,13 +96,13 @@ internal final class ReferenceExpPropertyTests { base: Call("getUserManager"), propertyName: "currentUser" ), - referenceType: "weak" + referenceType: .weak ) let syntax = reference.syntax let description = syntax.description #expect(description.contains("getUserManager().currentUser")) - #expect(reference.captureReferenceType == "weak") + #expect(reference.captureReferenceType == .weak) } } diff --git a/Tests/SyntaxKitTests/Unit/Integration/FrameworkCompatibilityTests.swift b/Tests/SyntaxKitTests/Unit/Integration/FrameworkCompatibilityTests.swift index fe34cd5..6061f0d 100644 --- a/Tests/SyntaxKitTests/Unit/Integration/FrameworkCompatibilityTests.swift +++ b/Tests/SyntaxKitTests/Unit/Integration/FrameworkCompatibilityTests.swift @@ -29,7 +29,7 @@ internal struct FrameworkCompatibilityTests { // MARK: - Error Handling Compatibility Tests - @Test internal func testThrowingTestCompatibility() throws { + @Test internal func testThrowingTestCompatibility() { // Ensure throws declaration works properly with @Test let function = Function("throwingFunction", returns: "String") { Parameter(name: "input", type: "String") @@ -39,7 +39,7 @@ internal struct FrameworkCompatibilityTests { } } - let generated = try function.syntax.description + let generated = function.syntax.description #expect(generated.contains("func throwingFunction")) } diff --git a/Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTests.swift b/Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTests.swift index 3319c29..f487e4d 100644 --- a/Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/Integration/OptionsMacroIntegrationTests.swift @@ -79,24 +79,16 @@ internal struct OptionsMacroIntegrationTests { @Test internal func testCompleteOptionsMacroWorkflow() { // This test demonstrates the complete workflow that the Options macro would use + // for an enum WITH raw values - // Step 1: Determine if enum has raw values (simulated) - let hasRawValues = true let enumName = "TestEnum" - // Step 2: Create the appropriate mappedValues variable - let mappedValuesVariable: Variable - if hasRawValues { - let keyValues: [Int: String] = [1: "first", 2: "second", 3: "third"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues) - .withExplicitType().static() - } else { - let caseNames: [String] = ["first", "second", "third"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames) - .withExplicitType().static() - } - - // Step 3: Create the extension + // Create the mappedValues variable for enum with raw values + let keyValues: [Int: String] = [1: "first", 2: "second", 3: "third"] + let mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues) + .withExplicitType().static() + + // Create the extension let extensionDecl = Extension(enumName) { TypeAlias("MappedType", equals: "String") mappedValuesVariable @@ -117,19 +109,12 @@ internal struct OptionsMacroIntegrationTests { @Test internal func testOptionsMacroWorkflowWithoutRawValues() { // Test the workflow for enums without raw values - let hasRawValues = false let enumName = "SimpleEnum" - let mappedValuesVariable: Variable - if hasRawValues { - let keyValues: [Int: String] = [1: "first", 2: "second"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: keyValues) - .withExplicitType().static() - } else { - let caseNames: [String] = ["first", "second"] - mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames) - .withExplicitType().static() - } + // Create the mappedValues variable for enum without raw values + let caseNames: [String] = ["first", "second"] + let mappedValuesVariable = Variable(.let, name: "mappedValues", equals: caseNames) + .withExplicitType().static() let extensionDecl = Extension(enumName) { TypeAlias("MappedType", equals: "String") diff --git a/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift b/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift index 480bcc4..42de7ed 100644 --- a/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift +++ b/Tests/SyntaxKitTests/Unit/SwiftUIFeatureTests.swift @@ -37,7 +37,7 @@ import Testing internal func testSwiftUIExample() throws { // Test the onToggle variable with closure type and attributes let onToggleVariable = Variable(.let, name: "onToggle", type: "(Date) -> Void") - .access("private") + .access(.private) let generatedCode = onToggleVariable.generateCode() let expectedCode = "private let onToggle: (Date) -> Void" @@ -87,25 +87,25 @@ import Testing @Test("Reference method supports different reference types") internal func testReferenceMethodSupportsDifferentTypes() throws { // Test weak reference - let weakRef = VariableExp("self").reference("weak") + let weakRef = VariableExp("self").reference(.weak) // The ReferenceExp itself just shows the base variable name let weakGenerated = weakRef.syntax.description #expect(weakGenerated.contains("self")) // Test unowned reference - let unownedRef = VariableExp("self").reference("unowned") + let unownedRef = VariableExp("self").reference(.unowned) let unownedGenerated = unownedRef.syntax.description #expect(unownedGenerated.contains("self")) // Verify that the reference types are stored correctly if let weakRefExp = weakRef as? ReferenceExp { - #expect(weakRefExp.captureReferenceType == "weak") + #expect(weakRefExp.captureReferenceType == .weak) } else { #expect(false, "Expected ReferenceExp type") } if let unownedRefExp = unownedRef as? ReferenceExp { - #expect(unownedRefExp.captureReferenceType == "unowned") + #expect(unownedRefExp.captureReferenceType == .unowned) } else { #expect(false, "Expected ReferenceExp type") } @@ -116,7 +116,7 @@ import Testing // Test weak reference in closure capture let weakClosure = Closure( capture: { - ParameterExp(unlabeled: VariableExp("self").reference("weak")) + ParameterExp(unlabeled: VariableExp("self").reference(.weak)) }, body: { VariableExp("self").optional().call("handleData") { @@ -126,13 +126,12 @@ import Testing ) let weakGenerated = weakClosure.syntax.description - print("Weak closure generated:\n\(weakGenerated)") #expect(weakGenerated.contains("[weak self]")) // Test unowned reference in closure capture let unownedClosure = Closure( capture: { - ParameterExp(unlabeled: VariableExp("self").reference("unowned")) + ParameterExp(unlabeled: VariableExp("self").reference(.unowned)) }, body: { VariableExp("self").call("handleData") { @@ -142,7 +141,6 @@ import Testing ) let unownedGenerated = unownedClosure.syntax.description - print("Unowned closure generated:\n\(unownedGenerated)") #expect(unownedGenerated.contains("[unowned self]")) } } diff --git a/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift b/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift index a8bb171..795dba7 100644 --- a/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift +++ b/Tests/SyntaxKitTests/Unit/Variables/VariableCoverageTests.swift @@ -44,7 +44,7 @@ internal final class VariableCoverageTests { internal func testBuildAccessModifierPublic() { // Test the "public" case in buildAccessModifier let variable = Variable(.let, name: "test", equals: "value") - .access("public") + .access(.public) let syntax = variable.syntax let description = syntax.description @@ -58,7 +58,7 @@ internal final class VariableCoverageTests { internal func testBuildAccessModifierInternal() { // Test the "internal" case in buildAccessModifier let variable = Variable(.let, name: "test", equals: "value") - .access("internal") + .access(.internal) let syntax = variable.syntax let description = syntax.description @@ -72,7 +72,7 @@ internal final class VariableCoverageTests { internal func testBuildAccessModifierFileprivate() { // Test the "fileprivate" case in buildAccessModifier let variable = Variable(.let, name: "test", equals: "value") - .access("fileprivate") + .access(.fileprivate) let syntax = variable.syntax let description = syntax.description @@ -81,20 +81,6 @@ internal final class VariableCoverageTests { #expect(description.contains("fileprivate let test = \"value\"")) } - /// Tests the default case in buildAccessModifier (unknown access modifier). - @Test("Build access modifier default") - internal func testBuildAccessModifierDefault() { - // Test the default case in buildAccessModifier (unknown access modifier) - let variable = Variable(.let, name: "test", equals: "value") - .access("unknown") - - let syntax = variable.syntax - let description = syntax.description - - // Should fallback to public - #expect(description.contains("public let test = \"value\"")) - } - // MARK: - Variable.swift Coverage Tests /// Tests the fallback type case in Variable initializer. From 7338cc091dc88e9204b7753c8721bfd2c30a1558 Mon Sep 17 00:00:00 2001 From: leogdion Date: Wed, 25 Jun 2025 19:22:22 -0400 Subject: [PATCH 10/10] Cleaning up Documentation (#84) --- .swiftlint.yml | 2 +- Examples/Completed/macro_tutorial/code.swift | 225 +++++++++++++ Examples/Completed/macro_tutorial/dsl.swift | 276 +++++++++++++++ Examples/Remaining/result_builders/code.swift | 58 ---- Package.resolved | 20 +- Package.swift | 3 +- .../CodeBlocks/CodeBlockBuilder.swift | 2 +- .../CodeBlocks/CodeBlockBuilderResult.swift | 2 +- .../SyntaxKit/CodeBlocks/EmptyCodeBlock.swift | 6 +- .../SyntaxKit/CodeBlocks/ExprCodeBlock.swift | 2 +- .../SyntaxKit/Collections/ArrayLiteral.swift | 15 +- .../Collections/CodeBlockableLiteral.swift | 33 ++ .../Collections/DictionaryLiteral.swift | 17 +- .../Collections/DictionaryValue.swift | 5 +- .../Collections/PatternCodeBlock.swift | 33 ++ ...ift => PatternConvertableCollection.swift} | 8 +- Sources/SyntaxKit/Collections/Tuple.swift | 6 +- .../Collections/TupleAssignment.swift | 12 +- ...eLiteral.swift => TupleLiteralArray.swift} | 17 +- .../SyntaxKit/Collections/TuplePattern.swift | 4 +- Sources/SyntaxKit/ControlFlow/For.swift | 2 +- Sources/SyntaxKit/ControlFlow/Guard.swift | 8 +- Sources/SyntaxKit/ControlFlow/If.swift | 8 +- Sources/SyntaxKit/ControlFlow/Switch.swift | 4 +- .../SyntaxKit/ControlFlow/SwitchCase.swift | 31 +- Sources/SyntaxKit/ControlFlow/While.swift | 6 +- Sources/SyntaxKit/Core/AccessModifier.swift | 2 +- .../SyntaxKit/Core/CaptureReferenceType.swift | 4 +- Sources/SyntaxKit/Core/CodeBlock.swift | 11 +- .../SyntaxKit/Core/ExprCodeBlockBuilder.swift | 5 +- Sources/SyntaxKit/Core/Line.swift | 4 +- .../SyntaxKit/Core/PatternConvertible.swift | 2 +- .../Core/PatternConvertibleBuilder.swift | 5 +- .../SyntaxKit/Core/TypeRepresentable.swift | 4 +- Sources/SyntaxKit/Declarations/Class.swift | 2 +- Sources/SyntaxKit/Declarations/Enum.swift | 2 +- .../SyntaxKit/Declarations/Extension.swift | 2 +- Sources/SyntaxKit/Declarations/Import.swift | 2 +- Sources/SyntaxKit/Declarations/Init.swift | 16 +- Sources/SyntaxKit/Declarations/Protocol.swift | 2 +- Sources/SyntaxKit/Declarations/Struct.swift | 2 +- .../SyntaxKit/Declarations/TypeAlias.swift | 2 +- .../Documentation.docc/Documentation.md | 79 ++++- .../Creating-Macros-with-SyntaxKit.md | 314 ++++++++++++++++++ .../ErrorHandling/CatchBuilder.swift | 2 +- Sources/SyntaxKit/Expressions/Call.swift | 2 +- .../Expressions/Closure+Capture.swift | 4 +- Sources/SyntaxKit/Expressions/Closure.swift | 16 +- .../ClosureParameterBuilderResult.swift | 2 +- .../SyntaxKit/Expressions/ClosureType.swift | 6 +- .../SyntaxKit/Expressions/ConditionalOp.swift | 6 +- .../Expressions/FunctionCallExp.swift | 10 +- .../Expressions/Literal+Convenience.swift | 4 +- Sources/SyntaxKit/Expressions/Literal.swift | 9 +- .../SyntaxKit/Expressions/LiteralValue.swift | 2 +- .../NegatedPropertyAccessExp.swift | 12 +- .../Expressions/OptionalChainingExp.swift | 23 +- .../SyntaxKit/Expressions/PlusAssign.swift | 25 ++ .../Expressions/PropertyAccessExp.swift | 18 +- .../Expressions/PropertyAccessible.swift | 40 +++ .../SyntaxKit/Expressions/ReferenceExp.swift | 6 +- Sources/SyntaxKit/Expressions/Task.swift | 102 ------ .../Functions/Function+Effects.swift | 4 +- Sources/SyntaxKit/Functions/Function.swift | 4 +- .../Parameters/ParameterBuilderResult.swift | 2 +- .../ParameterExpBuilderResult.swift | 2 +- Sources/SyntaxKit/Parser/SyntaxType.swift | 2 +- .../Patterns/LetBindingPattern.swift | 6 +- .../SyntaxKit/Utilities/CodeBlockable.swift | 2 +- .../Utilities/CommentBuilderResult.swift | 2 +- .../Utilities/PropertyRequirement.swift | 2 +- .../Variable+LiteralInitializers.swift | 12 +- .../Variable+TypedInitializers.swift | 14 +- .../SyntaxKit/Variables/VariableDecl.swift | 97 ------ Sources/SyntaxKit/Variables/VariableExp.swift | 33 +- .../SyntaxKit/Variables/VariableKind.swift | 4 +- .../Integration/BlackjackCardTests.swift | 3 +- .../Integration/BlackjackTests.swift | 5 +- .../Integration/CommentTests.swift | 3 +- .../CompleteProtocolsExampleTests.swift | 21 +- .../Integration/ConcurrencyExampleTests.swift | 3 +- .../ConditionalsExampleTests.swift | 3 +- .../Integration/ForLoopsExampleTests.swift | 3 +- .../Integration/SwiftUIExampleTests.swift | 3 +- .../Unit/Expressions/LiteralValueTests.swift | 32 +- .../Migration/CodeStyleMigrationTests.swift | 2 +- 86 files changed, 1294 insertions(+), 524 deletions(-) create mode 100644 Examples/Completed/macro_tutorial/code.swift create mode 100644 Examples/Completed/macro_tutorial/dsl.swift delete mode 100644 Examples/Remaining/result_builders/code.swift create mode 100644 Sources/SyntaxKit/Collections/CodeBlockableLiteral.swift create mode 100644 Sources/SyntaxKit/Collections/PatternCodeBlock.swift rename Sources/SyntaxKit/Collections/{TuplePatternCodeBlock.swift => PatternConvertableCollection.swift} (93%) rename Sources/SyntaxKit/Collections/{TupleLiteral.swift => TupleLiteralArray.swift} (89%) create mode 100644 Sources/SyntaxKit/Documentation.docc/Tutorials/Creating-Macros-with-SyntaxKit.md create mode 100644 Sources/SyntaxKit/Expressions/PropertyAccessible.swift delete mode 100644 Sources/SyntaxKit/Expressions/Task.swift delete mode 100644 Sources/SyntaxKit/Variables/VariableDecl.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 8623ed2..3f09d23 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -77,7 +77,7 @@ opt_in_rules: - strong_iboutlet - toggle_bool # - trailing_closure - - type_contents_order +# - type_contents_order - unavailable_function - unneeded_parentheses_in_closure_argument - unowned_variable_capture diff --git a/Examples/Completed/macro_tutorial/code.swift b/Examples/Completed/macro_tutorial/code.swift new file mode 100644 index 0000000..789c72d --- /dev/null +++ b/Examples/Completed/macro_tutorial/code.swift @@ -0,0 +1,225 @@ +import Foundation + +// MARK: - Macro Tutorial Examples +// This file demonstrates the concepts from the "Creating Macros with SyntaxKit" tutorial + +// MARK: - Example 1: Extension Macro Usage +// This shows how the @MyMacro would be used (as defined in the tutorial) + +protocol MyProtocol { + var description: String { get } +} + +// Example of what the macro would generate: +@MyMacro +enum Color: String { + case red = "red" + case green = "green" + case blue = "blue" +} + +// The macro would generate: +// extension Color: MyProtocol { +// typealias MyType = String +// static let myProperty = ["red", "green", "blue"] +// var description: String { +// return myProperty.joined(separator: ", ") +// } +// } +// +// struct ColorWrapper { +// let value: Color +// init(value: Color) { +// self.value = value +// } +// var description: String { +// return value.description +// } +// } + +// MARK: - Example 2: Freestanding Expression Macro Usage +// This shows how the #stringify macro would be used + +// let result = #stringify(42 + 8) +// result would be (50, "42 + 8") + +// MARK: - Example 3: Complex Macro Generation +// This shows what a complex macro might generate + +struct User { + var status: UserStatus + var name: String +} + +enum UserStatus: String { + case active = "active" + case inactive = "inactive" + case pending = "pending" +} + +// A complex macro might generate an extension like this: +extension User { + enum Status: String { + case active = "active" + case inactive = "inactive" + case pending = "pending" + } + + var isValid: Bool { + if status == .active { + return true + } else { + return false + } + } + + func updateStatus(newStatus: Status) { + status = newStatus + print("Status updated to \(newStatus)") + } + + static func createDefault() -> User { + return User(status: .pending, name: "Default") + } +} + +// MARK: - Example 4: SyntaxKit Code Generation +// This shows how SyntaxKit would be used to generate the above code + +import SyntaxKit + +// Example of generating the User extension using SyntaxKit +let userExtension = Extension("User") { + // Add a nested enum + Enum("Status") { + EnumCase("active").equals("active") + EnumCase("inactive").equals("inactive") + EnumCase("pending").equals("pending") + }.inherits("String") + + // Add a computed property with complex logic + ComputedProperty("isValid") { + If(VariableExp("status == .active"), then: { + Return { Literal.boolean(true) } + }, else: { + Return { Literal.boolean(false) } + }) + } + + // Add a method with parameters + Function("updateStatus", parameters: [Parameter("newStatus", type: "Status")]) { + Assignment("status", VariableExp("newStatus")) + Call("print") { + ParameterExp(unlabeled: "\"Status updated to \\(newStatus)\"") + } + } + + // Add a static method + Function("createDefault", parameters: []) { + Return { + Init("User") { + Parameter(name: "status", value: ".pending") + Parameter(name: "name", value: "\"Default\"") + } + } + }.static() + +}.inherits("Identifiable", "Codable") + +// MARK: - Example 5: Error Handling in Macros +// This shows how macros should handle errors + +enum MacroError: Error, CustomStringConvertible { + case onlyWorksWithEnums + case invalidCaseName(String) + case missingRawValue + + var description: String { + switch self { + case .onlyWorksWithEnums: + return "This macro can only be applied to enums" + case .invalidCaseName(let name): + return "Invalid case name: \(name)" + case .missingRawValue: + return "Enum cases must have raw values" + } + } +} + +// MARK: - Example 6: Testing Macros +// This shows how macros should be tested + +/* +// Example test for the MyMacro +func testExtensionMacro() throws { + assertMacroExpansion( + """ + @MyMacro + enum Color: String { + case red = "red" + case blue = "blue" + } + """, + expandedSource: """ + enum Color: String { + case red = "red" + case blue = "blue" + } + + extension Color: MyProtocol { + typealias MyType = String + static let myProperty = ["red", "blue"] + var description: String { + return myProperty.joined(separator: ", ") + } + } + + struct ColorWrapper { + let value: Color + init(value: Color) { + self.value = value + } + var description: String { + return value.description + } + } + """, + macros: ["MyMacro": MyMacro.self] + ) +} +*/ + +// MARK: - Example 7: Integration with SwiftSyntax +// This shows how SyntaxKit can be mixed with raw SwiftSyntax + +/* +// You can mix SyntaxKit with raw SwiftSyntax +let syntaxKitStruct = Struct("Generated") { + Variable(.let, name: "value", type: "String") +} + +// Convert to SwiftSyntax and modify +var structDecl = syntaxKitStruct.syntax.as(StructDeclSyntax.self)! +structDecl = structDecl.with(\.modifiers, DeclModifierListSyntax { + DeclModifierSyntax(name: .keyword(.public)) +}) + +// Convert back to SyntaxKit if needed +let modifiedStruct = Struct(structDecl) +*/ + +// MARK: - Usage Examples + +// Example usage of the generated code +let color = Color.red +print(color.description) // Would print: "red, green, blue" + +let user = User(status: .pending, name: "John") +print(user.isValid) // Would print: false + +user.updateStatus(newStatus: .active) +print(user.isValid) // Would print: true + +let defaultUser = User.createDefault() +print(defaultUser.name) // Would print: "Default" +print(defaultUser.status) // Would print: .pending \ No newline at end of file diff --git a/Examples/Completed/macro_tutorial/dsl.swift b/Examples/Completed/macro_tutorial/dsl.swift new file mode 100644 index 0000000..490051f --- /dev/null +++ b/Examples/Completed/macro_tutorial/dsl.swift @@ -0,0 +1,276 @@ +import SyntaxKit + +// MARK: - Macro Tutorial DSL Examples +// This file shows how SyntaxKit DSL would be used to generate the macro examples + +// MARK: - Example 1: Extension Macro Generation +// This shows how to generate the extension that @MyMacro would create + +let colorExtension = Extension("Color") { + // Add a type alias + TypeAlias("MyType", equals: "String") + + // Add a static property with case names + Variable(.let, name: "myProperty", equals: ["red", "green", "blue"]).static() + + // Add a computed property + ComputedProperty("description") { + Return { + VariableExp("myProperty.joined(separator: \", \")") + } + } +}.inherits("MyProtocol") + +// MARK: - Example 2: Peer Macro Generation +// This shows how to generate the wrapper struct that @MyMacro would create + +let colorWrapper = Struct("ColorWrapper") { + Variable(.let, name: "value", type: "Color") + + Init { + Parameter(name: "value", type: "Color") + } + + ComputedProperty("description") { + Return { + VariableExp("value.description") + } + } +} + +// MARK: - Example 3: Freestanding Expression Macro Generation +// This shows how to generate the tuple that #stringify would create + +let stringifyResult = Tuple { + VariableExp("42 + 8") + Literal.string("42 + 8") +} + +// MARK: - Example 4: Complex Extension Generation +// This shows how to generate a complex extension with multiple members + +let userExtension = Extension("User") { + // Add a nested enum + Enum("Status") { + EnumCase("active").equals("active") + EnumCase("inactive").equals("inactive") + EnumCase("pending").equals("pending") + }.inherits("String") + + // Add a computed property with complex logic + ComputedProperty("isValid") { + If(VariableExp("status == .active"), then: { + Return { Literal.boolean(true) } + }, else: { + Return { Literal.boolean(false) } + }) + } + + // Add a method with parameters + Function("updateStatus", parameters: [Parameter("newStatus", type: "Status")]) { + Assignment("status", VariableExp("newStatus")) + Call("print") { + ParameterExp(unlabeled: "\"Status updated to \\(newStatus)\"") + } + } + + // Add a static method + Function("createDefault", parameters: []) { + Return { + Init("User") { + Parameter(name: "status", value: ".pending") + Parameter(name: "name", value: "\"Default\"") + } + } + }.static() + +}.inherits("Identifiable", "Codable") + +// MARK: - Example 5: Error Handling Structure +// This shows how to generate error handling code + +let macroError = Enum("MacroError") { + EnumCase("onlyWorksWithEnums") + EnumCase("invalidCaseName").associatedValue("name", type: "String") + EnumCase("missingRawValue") +}.inherits("Error", "CustomStringConvertible") + +// MARK: - Example 6: Test Code Generation +// This shows how to generate test code for macros + +let testFunction = Function("testExtensionMacro", parameters: []) { + Call("assertMacroExpansion") { + ParameterExp(name: "input", value: "\"\"\"\n@MyMacro\nenum Color: String {\n case red = \"red\"\n case blue = \"blue\"\n}\n\"\"\"") + ParameterExp(name: "expected", value: "\"\"\"\nenum Color: String {\n case red = \"red\"\n case blue = \"blue\"\n}\n\nextension Color: MyProtocol {\n typealias MyType = String\n static let myProperty = [\"red\", \"blue\"]\n var description: String {\n return myProperty.joined(separator: \", \")\n }\n}\n\nstruct ColorWrapper {\n let value: Color\n init(value: Color) {\n self.value = value\n }\n var description: String {\n return value.description\n }\n}\n\"\"\"") + ParameterExp(name: "macros", value: "[\"MyMacro\": MyMacro.self]") + } +}.throws() + +// MARK: - Example 7: Integration Example +// This shows how to mix SyntaxKit with raw SwiftSyntax + +let baseStruct = Struct("Generated") { + Variable(.let, name: "value", type: "String") +} + +// Convert to SwiftSyntax and modify (this would be done in the macro) +// var structDecl = baseStruct.syntax.as(StructDeclSyntax.self)! +// structDecl = structDecl.with(\.modifiers, DeclModifierListSyntax { +// DeclModifierSyntax(name: .keyword(.public)) +// }) + +// MARK: - Example 8: Protocol Generation +// This shows how to generate protocols that macros might need + +let myProtocol = Protocol("MyProtocol") { + PropertyRequirement("description", type: "String", access: .get) +} + +// MARK: - Example 9: Complex Control Flow Generation +// This shows how to generate complex control flow in macros + +let complexFunction = Function("processData", parameters: [Parameter("data", type: "[String]")]) { + Variable(.var, name: "result", equals: "[]") + + For(VariableExp("item"), in: VariableExp("data"), then: { + If(VariableExp("item.hasPrefix(\"test\")"), then: { + Call("result.append") { + ParameterExp(unlabeled: "item.uppercased()") + } + }, else: { + Call("result.append") { + ParameterExp(unlabeled: "item.lowercased()") + } + }) + }) + + Return { + VariableExp("result") + } +} + +// MARK: - Example 10: Nested Structure Generation +// This shows how to generate nested structures + +let complexStruct = Struct("ComplexStruct") { + // Nested enum + Enum("NestedEnum") { + EnumCase("case1") + EnumCase("case2").equals("value2") + }.inherits("String") + + // Nested struct + Struct("NestedStruct") { + Variable(.let, name: "id", type: "UUID") + Variable(.var, name: "name", type: "String") + + Init { + Parameter(name: "name", type: "String") + } + + ComputedProperty("displayName") { + Return { + VariableExp("name.isEmpty ? \"Unknown\" : name") + } + } + } + + // Properties + Variable(.let, name: "enumValue", type: "NestedEnum") + Variable(.var, name: "structValue", type: "NestedStruct") + + // Methods + Function("updateName", parameters: [Parameter("newName", type: "String")]) { + Assignment("structValue.name", VariableExp("newName")) + Call("print") { + ParameterExp(unlabeled: "\"Name updated to: \\(newName)\"") + } + } +} + +// MARK: - Example 11: Switch Statement Generation +// This shows how to generate switch statements in macros + +let switchFunction = Function("handleStatus", parameters: [Parameter("status", type: "UserStatus")]) { + Switch("status") { + SwitchCase(".active") { + Call("print") { + ParameterExp(unlabeled: "\"User is active\"") + } + Return { Literal.boolean(true) } + } + SwitchCase(".inactive") { + Call("print") { + ParameterExp(unlabeled: "\"User is inactive\"") + } + Return { Literal.boolean(false) } + } + SwitchCase(".pending") { + Call("print") { + ParameterExp(unlabeled: "\"User status is pending\"") + } + Return { Literal.boolean(false) } + } + Default { + Call("print") { + ParameterExp(unlabeled: "\"Unknown status\"") + } + Return { Literal.boolean(false) } + } + } +} + +// MARK: - Example 12: Guard Statement Generation +// This shows how to generate guard statements in macros + +let guardFunction = Function("validateUser", parameters: [Parameter("user", type: "User?")]) { + Guard { + Let("user", "user") + } else: { + Call("print") { + ParameterExp(unlabeled: "\"User is nil\"") + } + Return { Literal.boolean(false) } + } + + Guard { + Let("name", "user.name") + Let("nameLength", "name.count") + } else: { + Call("print") { + ParameterExp(unlabeled: "\"Invalid user name\"") + } + Return { Literal.boolean(false) } + } + + If(VariableExp("nameLength > 0"), then: { + Call("print") { + ParameterExp(unlabeled: "\"User \\(name) is valid\"") + } + Return { Literal.boolean(true) } + }, else: { + Call("print") { + ParameterExp(unlabeled: "\"User name is empty\"") + } + Return { Literal.boolean(false) } + }) +} + +// MARK: - Generate All Examples + +let allExamples = Group { + colorExtension + colorWrapper + stringifyResult + userExtension + macroError + testFunction + myProtocol + complexFunction + complexStruct + switchFunction + guardFunction +} + +// Print the generated code +print(allExamples.generateCode()) \ No newline at end of file diff --git a/Examples/Remaining/result_builders/code.swift b/Examples/Remaining/result_builders/code.swift deleted file mode 100644 index 148b74e..0000000 --- a/Examples/Remaining/result_builders/code.swift +++ /dev/null @@ -1,58 +0,0 @@ - -var vendingMachine = VendingMachine() -vendingMachine.coinsDeposited = 8 -do { - try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) - print("Success! Yum.") -} catch VendingMachineError.invalidSelection { - print("Invalid Selection.") -} catch VendingMachineError.outOfStock { - print("Out of Stock.") -} catch VendingMachineError.insufficientFunds(let coinsNeeded) { - print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.") -} catch { - print("Unexpected error: \(error).") -} - -func summarize(_ ratings: [Int]) throws(StatisticsError) { - guard !ratings.isEmpty else { throw .noRatings } -} - -// MARK: - Task Groups -func fetchMultipleUsers(ids: [Int]) async throws -> [String] { - try await withThrowingTaskGroup(of: String.self) { group in - for id in ids { - group.addTask { - try await fetchUserData(id: id) - } - } - - var results: [String] = [] - for try await result in group { - results.append(result) - } - return results - } -} - -// Demonstrate concurrent tasks -print("\nFetching user data and posts concurrently...") -async let data = fetchUserData(id: 1) -async let posts = fetchUserPosts(id: 1) -let (fetchedData, fetchedPosts) = try await (data, posts) -print("Data: \(fetchedData)") -print("Posts: \(fetchedPosts)") - - -Task { - _ = try await fetchUserData(id: 1) -} - -Task { @MainActor [unowned self] in - _ = try await fetchUserData(id: 1) -} - - -func nonThrowingFunction() throws(Never) { - -} \ No newline at end of file diff --git a/Package.resolved b/Package.resolved index fc91c87..505dfe4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,6 +1,24 @@ { - "originHash" : "79e6b2b96efe3d22ee340e623938e0363d6ce8fb0edfd7ccdf90e98b766f59ec", + "originHash" : "1f871cf2ab4e2e02f2c226ed2c4970de7f17ba4d8620629c7a18997d0feb58d2", "pins" : [ + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-docc-plugin", + "state" : { + "revision" : "d1691545d53581400b1de9b0472d45eb25c19fed", + "version" : "1.4.4" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", + "version" : "1.0.0" + } + }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 6a95649..84b7a3a 100644 --- a/Package.swift +++ b/Package.swift @@ -24,7 +24,8 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/apple/swift-syntax.git", from: "601.0.1") + .package(url: "https://github.com/apple/swift-syntax.git", from: "601.0.1"), + .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.4.0") ], targets: [ .target( diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift index 74c241f..5e93805 100644 --- a/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilder.swift @@ -30,7 +30,7 @@ import Foundation /// A protocol for types that can build a ``CodeBlock``. -public protocol CodeBlockBuilder { +public protocol CodeBlockBuilder: Sendable, Equatable { /// The type of ``CodeBlock`` that this builder creates. associatedtype Result: CodeBlock /// Builds the ``CodeBlock``. diff --git a/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift index 4340d5c..d5f1280 100644 --- a/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift +++ b/Sources/SyntaxKit/CodeBlocks/CodeBlockBuilderResult.swift @@ -31,7 +31,7 @@ import Foundation /// A result builder for creating arrays of ``CodeBlock``s. @resultBuilder -public enum CodeBlockBuilderResult { +public enum CodeBlockBuilderResult: Sendable { /// Builds a block of ``CodeBlock``s. public static func buildBlock(_ components: CodeBlock...) -> [CodeBlock] { components diff --git a/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift index 6db397c..07636f4 100644 --- a/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift +++ b/Sources/SyntaxKit/CodeBlocks/EmptyCodeBlock.swift @@ -30,10 +30,10 @@ import Foundation import SwiftSyntax -/// An empty ``CodeBlock``. -public struct EmptyCodeBlock: CodeBlock { +/// An empty code block that generates no syntax. +internal struct EmptyCodeBlock: CodeBlock, Sendable, Equatable { /// The syntax for an empty code block. - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { StringSegmentSyntax(content: .unknown("")) } } diff --git a/Sources/SyntaxKit/CodeBlocks/ExprCodeBlock.swift b/Sources/SyntaxKit/CodeBlocks/ExprCodeBlock.swift index 34794ba..382dc95 100644 --- a/Sources/SyntaxKit/CodeBlocks/ExprCodeBlock.swift +++ b/Sources/SyntaxKit/CodeBlocks/ExprCodeBlock.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A protocol for types that can be represented as an ExprSyntax node. -public protocol ExprCodeBlock { +public protocol ExprCodeBlock: Sendable { /// The SwiftSyntax expression representation of the code block. var exprSyntax: ExprSyntax { get } } diff --git a/Sources/SyntaxKit/Collections/ArrayLiteral.swift b/Sources/SyntaxKit/Collections/ArrayLiteral.swift index f419dae..31ce7a3 100644 --- a/Sources/SyntaxKit/Collections/ArrayLiteral.swift +++ b/Sources/SyntaxKit/Collections/ArrayLiteral.swift @@ -30,23 +30,24 @@ import Foundation /// An array literal value that can be used as a literal. -public struct ArrayLiteral: LiteralValue, CodeBlockable { - public let elements: [Literal] +internal struct ArrayLiteral: LiteralValue, CodeBlockable { + internal let elements: [Literal] /// Creates an array with the given elements. /// - Parameter elements: The array elements. - public init(_ elements: [Literal]) { + internal init(_ elements: [Literal]) { self.elements = elements } /// The code block representation of this array literal. - public var codeBlock: CodeBlock { + internal var codeBlock: CodeBlock { Literal.array(elements) } /// The Swift type name for this array. - public var typeName: String { + internal var typeName: String { if elements.isEmpty { + // TODO: Consider more specific type inference for empty arrays return "[Any]" } let elementType = elements.first?.typeName ?? "Any" @@ -54,7 +55,7 @@ public struct ArrayLiteral: LiteralValue, CodeBlockable { } /// Renders this array as a Swift literal string. - public var literalString: String { + internal var literalString: String { let elementStrings = elements.map { element in switch element { case .integer(let value): return String(value) @@ -64,7 +65,7 @@ public struct ArrayLiteral: LiteralValue, CodeBlockable { case .nil: return "nil" case .ref(let value): return value case .tuple(let tupleElements): - let tuple = TupleLiteral(tupleElements) + let tuple = TupleLiteralArray(tupleElements) return tuple.literalString case .array(let arrayElements): let array = ArrayLiteral(arrayElements) diff --git a/Sources/SyntaxKit/Collections/CodeBlockableLiteral.swift b/Sources/SyntaxKit/Collections/CodeBlockableLiteral.swift new file mode 100644 index 0000000..6e0e219 --- /dev/null +++ b/Sources/SyntaxKit/Collections/CodeBlockableLiteral.swift @@ -0,0 +1,33 @@ +// +// CodeBlockableLiteral.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// A protocol for tuple literal values that can be used as literals. +public typealias CodeBlockableLiteral = LiteralValue & CodeBlockable diff --git a/Sources/SyntaxKit/Collections/DictionaryLiteral.swift b/Sources/SyntaxKit/Collections/DictionaryLiteral.swift index 2843ec2..779621c 100644 --- a/Sources/SyntaxKit/Collections/DictionaryLiteral.swift +++ b/Sources/SyntaxKit/Collections/DictionaryLiteral.swift @@ -30,23 +30,24 @@ import Foundation /// A dictionary literal value that can be used as a literal. -public struct DictionaryLiteral: LiteralValue, CodeBlockable { - public let elements: [(Literal, Literal)] +internal struct DictionaryLiteral: LiteralValue, CodeBlockable { + internal let elements: [(Literal, Literal)] /// Creates a dictionary with the given key-value pairs. /// - Parameter elements: The dictionary key-value pairs. - public init(_ elements: [(Literal, Literal)]) { + internal init(_ elements: [(Literal, Literal)]) { self.elements = elements } /// The code block representation of this dictionary literal. - public var codeBlock: CodeBlock { + internal var codeBlock: CodeBlock { Literal.dictionary(elements) } /// The Swift type name for this dictionary. - public var typeName: String { + internal var typeName: String { if elements.isEmpty { + // TODO: Consider more specific type inference for empty dictionaries return "[Any: Any]" } let keyType = elements.first?.0.typeName ?? "Any" @@ -55,7 +56,7 @@ public struct DictionaryLiteral: LiteralValue, CodeBlockable { } /// Renders this dictionary as a Swift literal string. - public var literalString: String { + internal var literalString: String { let elementStrings = elements.map { key, value in let keyString: String let valueString: String @@ -68,7 +69,7 @@ public struct DictionaryLiteral: LiteralValue, CodeBlockable { case .nil: keyString = "nil" case .ref(let key): keyString = key case .tuple(let tupleElements): - let tuple = TupleLiteral(tupleElements) + let tuple = TupleLiteralArray(tupleElements) keyString = tuple.literalString case .array(let arrayElements): let array = ArrayLiteral(arrayElements) @@ -86,7 +87,7 @@ public struct DictionaryLiteral: LiteralValue, CodeBlockable { case .nil: valueString = "nil" case .ref(let value): valueString = value case .tuple(let tupleElements): - let tuple = TupleLiteral(tupleElements) + let tuple = TupleLiteralArray(tupleElements) valueString = tuple.literalString case .array(let arrayElements): let array = ArrayLiteral(arrayElements) diff --git a/Sources/SyntaxKit/Collections/DictionaryValue.swift b/Sources/SyntaxKit/Collections/DictionaryValue.swift index b1ac438..fb5ecd7 100644 --- a/Sources/SyntaxKit/Collections/DictionaryValue.swift +++ b/Sources/SyntaxKit/Collections/DictionaryValue.swift @@ -29,9 +29,8 @@ import SwiftSyntax -/// A protocol for types that can be used as dictionary keys or values. -/// This includes both Literal types and CodeBlock types that can be converted to expressions. -public protocol DictionaryValue { +/// A protocol for types that can be used as dictionary values. +public protocol DictionaryValue: Sendable { /// The expression syntax representation of this dictionary value. var exprSyntax: ExprSyntax { get } } diff --git a/Sources/SyntaxKit/Collections/PatternCodeBlock.swift b/Sources/SyntaxKit/Collections/PatternCodeBlock.swift new file mode 100644 index 0000000..3cf1a5f --- /dev/null +++ b/Sources/SyntaxKit/Collections/PatternCodeBlock.swift @@ -0,0 +1,33 @@ +// +// PatternCodeBlock.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Foundation + +/// A protocol for tuple patterns that can be used as CodeBlocks for for-in loops. +public typealias PatternCodeBlock = CodeBlock & PatternConvertible diff --git a/Sources/SyntaxKit/Collections/TuplePatternCodeBlock.swift b/Sources/SyntaxKit/Collections/PatternConvertableCollection.swift similarity index 93% rename from Sources/SyntaxKit/Collections/TuplePatternCodeBlock.swift rename to Sources/SyntaxKit/Collections/PatternConvertableCollection.swift index f5436d2..a3315cf 100644 --- a/Sources/SyntaxKit/Collections/TuplePatternCodeBlock.swift +++ b/Sources/SyntaxKit/Collections/PatternConvertableCollection.swift @@ -1,5 +1,5 @@ // -// TuplePatternCodeBlock.swift +// PatternConvertableCollection.swift // SyntaxKit // // Created by Leo Dion. @@ -30,14 +30,14 @@ import SwiftSyntax /// A tuple pattern that can be used as a CodeBlock for for-in loops. -public struct TuplePatternCodeBlock: CodeBlock, PatternConvertible { +internal struct PatternConvertableCollection: PatternCodeBlock { private let elements: [PatternConvertible?] internal init(elements: [PatternConvertible?]) { self.elements = elements } - public var patternSyntax: PatternSyntax { + internal var patternSyntax: PatternSyntax { let patternElements = TuplePatternElementListSyntax( elements.enumerated().map { index, element in let patternElement: TuplePatternElementSyntax @@ -70,7 +70,7 @@ public struct TuplePatternCodeBlock: CodeBlock, PatternConvertible { ) } - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { // For CodeBlock conformance, we return the pattern syntax as an expression // This is a bit of a hack, but it allows us to use TuplePatternCodeBlock in For loops patternSyntax diff --git a/Sources/SyntaxKit/Collections/Tuple.swift b/Sources/SyntaxKit/Collections/Tuple.swift index ab71880..7693579 100644 --- a/Sources/SyntaxKit/Collections/Tuple.swift +++ b/Sources/SyntaxKit/Collections/Tuple.swift @@ -43,14 +43,14 @@ public struct Tuple: CodeBlock { /// Creates a tuple pattern for switch cases. /// - Parameter elements: Array of pattern elements, where `nil` represents a wildcard pattern. - public static func pattern(_ elements: [PatternConvertible?]) -> TuplePattern { + public static func pattern(_ elements: [PatternConvertible?]) -> PatternConvertible { TuplePattern(elements: elements) } /// Creates a tuple pattern that can be used as a CodeBlock. /// - Parameter elements: Array of pattern elements, where `nil` represents a wildcard pattern. - public static func patternCodeBlock(_ elements: [PatternConvertible?]) -> TuplePatternCodeBlock { - TuplePatternCodeBlock(elements: elements) + public static func patternCodeBlock(_ elements: [PatternConvertible?]) -> PatternCodeBlock { + PatternConvertableCollection(elements: elements) } /// Marks this tuple as async. diff --git a/Sources/SyntaxKit/Collections/TupleAssignment.swift b/Sources/SyntaxKit/Collections/TupleAssignment.swift index e765f21..37701d7 100644 --- a/Sources/SyntaxKit/Collections/TupleAssignment.swift +++ b/Sources/SyntaxKit/Collections/TupleAssignment.swift @@ -31,7 +31,7 @@ import Foundation import SwiftSyntax /// A tuple assignment statement for destructuring multiple values. -public struct TupleAssignment: CodeBlock { +internal struct TupleAssignment: CodeBlock { private let elements: [String] private let value: CodeBlock private var isAsync: Bool = false @@ -42,14 +42,14 @@ public struct TupleAssignment: CodeBlock { /// - Parameters: /// - elements: The names of the variables to destructure into. /// - value: The expression to destructure. - public init(_ elements: [String], equals value: CodeBlock) { + internal init(_ elements: [String], equals value: CodeBlock) { self.elements = elements self.value = value } /// Marks this destructuring as async. /// - Returns: A copy of the destructuring marked as async. - public func async() -> Self { + internal func async() -> Self { var copy = self copy.isAsync = true return copy @@ -57,7 +57,7 @@ public struct TupleAssignment: CodeBlock { /// Marks this destructuring as throwing. /// - Returns: A copy of the destructuring marked as throwing. - public func throwing() -> Self { + internal func throwing() -> Self { var copy = self copy.isThrowing = true return copy @@ -65,14 +65,14 @@ public struct TupleAssignment: CodeBlock { /// Marks this destructuring as concurrent async (async let set). /// - Returns: A copy of the destructuring marked as async set. - public func asyncSet() -> Self { + internal func asyncSet() -> Self { var copy = self copy.isAsyncSet = true return copy } /// The syntax representation of this tuple assignment. - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { if isAsyncSet { return generateAsyncSetSyntax() } diff --git a/Sources/SyntaxKit/Collections/TupleLiteral.swift b/Sources/SyntaxKit/Collections/TupleLiteralArray.swift similarity index 89% rename from Sources/SyntaxKit/Collections/TupleLiteral.swift rename to Sources/SyntaxKit/Collections/TupleLiteralArray.swift index 0c3efaf..a64beab 100644 --- a/Sources/SyntaxKit/Collections/TupleLiteral.swift +++ b/Sources/SyntaxKit/Collections/TupleLiteralArray.swift @@ -1,5 +1,5 @@ // -// TupleLiteral.swift +// TupleLiteralArray.swift // SyntaxKit // // Created by Leo Dion. @@ -28,24 +28,25 @@ // import Foundation +import SwiftSyntax /// A tuple literal value that can be used as a literal. -public struct TupleLiteral: LiteralValue, CodeBlockable { - public let elements: [Literal?] +internal struct TupleLiteralArray: CodeBlockableLiteral { + internal let elements: [Literal?] /// Creates a tuple with the given elements. /// - Parameter elements: The tuple elements, where `nil` represents a wildcard. - public init(_ elements: [Literal?]) { + internal init(_ elements: [Literal?]) { self.elements = elements } /// The code block representation of this tuple literal. - public var codeBlock: CodeBlock { + internal var codeBlock: CodeBlock { Literal.tuple(elements) } /// The Swift type name for this tuple. - public var typeName: String { + internal var typeName: String { let elementTypes = elements.map { element in if let element = element { switch element { @@ -67,7 +68,7 @@ public struct TupleLiteral: LiteralValue, CodeBlockable { } /// Renders this tuple as a Swift literal string. - public var literalString: String { + internal var literalString: String { let elementStrings = elements.map { element in if let element = element { switch element { @@ -78,7 +79,7 @@ public struct TupleLiteral: LiteralValue, CodeBlockable { case .nil: return "nil" case .ref(let value): return value case .tuple(let tupleElements): - let tuple = TupleLiteral(tupleElements) + let tuple = TupleLiteralArray(tupleElements) return tuple.literalString case .array(let arrayElements): let array = ArrayLiteral(arrayElements) diff --git a/Sources/SyntaxKit/Collections/TuplePattern.swift b/Sources/SyntaxKit/Collections/TuplePattern.swift index f739aea..569b7f6 100644 --- a/Sources/SyntaxKit/Collections/TuplePattern.swift +++ b/Sources/SyntaxKit/Collections/TuplePattern.swift @@ -30,14 +30,14 @@ import SwiftSyntax /// A tuple pattern for switch cases. -public struct TuplePattern: PatternConvertible { +internal struct TuplePattern: PatternConvertible { private let elements: [PatternConvertible?] internal init(elements: [PatternConvertible?]) { self.elements = elements } - public var patternSyntax: PatternSyntax { + internal var patternSyntax: PatternSyntax { let patternElements = TuplePatternElementListSyntax( elements.enumerated().map { index, element in let patternElement: TuplePatternElementSyntax diff --git a/Sources/SyntaxKit/ControlFlow/For.swift b/Sources/SyntaxKit/ControlFlow/For.swift index 0bcc4b5..e33b8d2 100644 --- a/Sources/SyntaxKit/ControlFlow/For.swift +++ b/Sources/SyntaxKit/ControlFlow/For.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A `for-in` loop statement. -public struct For: CodeBlock { +public struct For: CodeBlock, Sendable { private let pattern: any CodeBlock & PatternConvertible private let sequence: CodeBlock private let whereClause: CodeBlock? diff --git a/Sources/SyntaxKit/ControlFlow/Guard.swift b/Sources/SyntaxKit/ControlFlow/Guard.swift index c64cbe9..99ce72e 100644 --- a/Sources/SyntaxKit/ControlFlow/Guard.swift +++ b/Sources/SyntaxKit/ControlFlow/Guard.swift @@ -30,14 +30,14 @@ import SwiftSyntax /// A `guard … else { … }` statement. -public struct Guard: CodeBlock { +public struct Guard: CodeBlock, Sendable { private let conditions: [CodeBlock] private let elseBody: [CodeBlock] /// Creates a `guard` statement. /// - Parameters: /// - condition: A ``CodeBlockBuilder`` that provides the condition expression. - /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + /// - elseBody: A ``CodeBlockBuilder`` that provides the body when the condition is false. public init( @CodeBlockBuilderResult _ condition: () throws -> [CodeBlock], @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] @@ -54,7 +54,7 @@ public struct Guard: CodeBlock { /// Creates a `guard` statement without a condition (uses true as default). /// - Parameters: - /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + /// - elseBody: A ``CodeBlockBuilder`` that provides the body when the condition is false. public init( @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] ) rethrows { @@ -67,7 +67,7 @@ public struct Guard: CodeBlock { /// Creates a `guard` statement with a string condition. /// - Parameters: /// - condition: The condition as a string. - /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + /// - elseBody: A ``CodeBlockBuilder`` that provides the body when the condition is false. public init( _ condition: String, @CodeBlockBuilderResult else elseBody: () throws -> [CodeBlock] diff --git a/Sources/SyntaxKit/ControlFlow/If.swift b/Sources/SyntaxKit/ControlFlow/If.swift index d5d87a8..ccef62f 100644 --- a/Sources/SyntaxKit/ControlFlow/If.swift +++ b/Sources/SyntaxKit/ControlFlow/If.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// An `if` statement. -public struct If: CodeBlock { +/// A Swift `if` statement. +public struct If: CodeBlock, Sendable { internal let conditions: [CodeBlock] internal let body: [CodeBlock] internal let elseBody: [CodeBlock]? @@ -125,7 +125,7 @@ public struct If: CodeBlock { /// - Parameters: /// - condition: A ``CodeBlockBuilder`` that provides the condition expression. /// - then: A ``CodeBlockBuilder`` that provides the body when the condition is true. - /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + /// - elseBody: A ``CodeBlockBuilder`` that provides the body when the condition is false. public init( @CodeBlockBuilderResult _ condition: () throws -> [CodeBlock], @CodeBlockBuilderResult then: () throws -> [CodeBlock], @@ -162,7 +162,7 @@ public struct If: CodeBlock { /// - Parameters: /// - condition: The condition as a string. /// - then: A ``CodeBlockBuilder`` that provides the body when the condition is true. - /// - else: A ``CodeBlockBuilder`` that provides the body when the condition is false. + /// - elseBody: A ``CodeBlockBuilder`` that provides the body when the condition is false. public init( _ condition: String, @CodeBlockBuilderResult then: () throws -> [CodeBlock], diff --git a/Sources/SyntaxKit/ControlFlow/Switch.swift b/Sources/SyntaxKit/ControlFlow/Switch.swift index 79d9ad3..2b4113e 100644 --- a/Sources/SyntaxKit/ControlFlow/Switch.swift +++ b/Sources/SyntaxKit/ControlFlow/Switch.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// A `switch` statement. -public struct Switch: CodeBlock { +/// A Swift `switch` statement. +public struct Switch: CodeBlock, Sendable { private let expression: CodeBlock private let cases: [CodeBlock] diff --git a/Sources/SyntaxKit/ControlFlow/SwitchCase.swift b/Sources/SyntaxKit/ControlFlow/SwitchCase.swift index 4999e8c..43c5348 100644 --- a/Sources/SyntaxKit/ControlFlow/SwitchCase.swift +++ b/Sources/SyntaxKit/ControlFlow/SwitchCase.swift @@ -31,15 +31,16 @@ import SwiftSyntax /// A `case` in a `switch` statement. public struct SwitchCase: CodeBlock { - private let patterns: [Any] + private let patterns: [PatternConvertible] private let body: [CodeBlock] /// Creates a `case` for a `switch` statement. /// - Parameters: - /// - patterns: The patterns to match for the case. Can be `PatternConvertible`, - /// `CodeBlock`, or `SwitchLet` for value binding. + /// - patterns: The patterns to match for the case. Must conform to `PatternConvertible`. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. - public init(_ patterns: Any..., @CodeBlockBuilderResult content: () throws -> [CodeBlock]) + public init( + _ patterns: PatternConvertible..., @CodeBlockBuilderResult content: () throws -> [CodeBlock] + ) rethrows { self.patterns = patterns @@ -51,7 +52,7 @@ public struct SwitchCase: CodeBlock { /// - conditional: A ``CodeBlockBuilder`` that provides the conditional patterns for the case. /// - content: A ``CodeBlockBuilder`` that provides the body of the case. public init( - @CodeBlockBuilderResult conditional: () throws -> [CodeBlock], + @CodeBlockBuilderResult conditional: () throws -> [PatternConvertible], @CodeBlockBuilderResult content: () throws -> [CodeBlock] ) rethrows { self.patterns = try conditional() @@ -61,25 +62,7 @@ public struct SwitchCase: CodeBlock { public var switchCaseSyntax: SwitchCaseSyntax { let caseItems = SwitchCaseItemListSyntax( patterns.enumerated().compactMap { index, pattern -> SwitchCaseItemSyntax? in - let patternSyntax: PatternSyntax - - if let patternConvertible = pattern as? PatternConvertible { - patternSyntax = patternConvertible.patternSyntax - } else if let variableExp = pattern as? VariableExp { - // Handle VariableExp specially - convert to identifier pattern - patternSyntax = PatternSyntax( - IdentifierPatternSyntax(identifier: .identifier(variableExp.name)) - ) - } else if let codeBlock = pattern as? CodeBlock { - // Convert CodeBlock to expression pattern - let expr = ExprSyntax( - fromProtocol: codeBlock.syntax.as(ExprSyntax.self) - ?? DeclReferenceExprSyntax(baseName: .identifier("")) - ) - patternSyntax = PatternSyntax(ExpressionPatternSyntax(expression: expr)) - } else { - return nil - } + let patternSyntax = pattern.patternSyntax var item = SwitchCaseItemSyntax(pattern: patternSyntax) if index < patterns.count - 1 { diff --git a/Sources/SyntaxKit/ControlFlow/While.swift b/Sources/SyntaxKit/ControlFlow/While.swift index 4bd03b6..4f1db47 100644 --- a/Sources/SyntaxKit/ControlFlow/While.swift +++ b/Sources/SyntaxKit/ControlFlow/While.swift @@ -29,9 +29,9 @@ import SwiftSyntax -/// A `while` loop statement. -public struct While: CodeBlock { - public enum Kind { +/// A Swift `while` loop. +public struct While: CodeBlock, Sendable { + public enum Kind: Sendable { case `while` case repeatWhile } diff --git a/Sources/SyntaxKit/Core/AccessModifier.swift b/Sources/SyntaxKit/Core/AccessModifier.swift index edd3631..4b68152 100644 --- a/Sources/SyntaxKit/Core/AccessModifier.swift +++ b/Sources/SyntaxKit/Core/AccessModifier.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// Represents Swift access modifiers. -public enum AccessModifier: CaseIterable { +public enum AccessModifier: CaseIterable, Sendable, Equatable { case `public` case `private` case `internal` diff --git a/Sources/SyntaxKit/Core/CaptureReferenceType.swift b/Sources/SyntaxKit/Core/CaptureReferenceType.swift index 582eba6..8c58d28 100644 --- a/Sources/SyntaxKit/Core/CaptureReferenceType.swift +++ b/Sources/SyntaxKit/Core/CaptureReferenceType.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// Represents Swift capture reference types for closures. -public enum CaptureReferenceType: CaseIterable { +/// Represents the type of reference capture in closures. +public enum CaptureReferenceType: CaseIterable, Sendable, Equatable { case weak case unowned diff --git a/Sources/SyntaxKit/Core/CodeBlock.swift b/Sources/SyntaxKit/Core/CodeBlock.swift index e29c41d..63ed1af 100644 --- a/Sources/SyntaxKit/Core/CodeBlock.swift +++ b/Sources/SyntaxKit/Core/CodeBlock.swift @@ -31,7 +31,7 @@ import Foundation import SwiftSyntax /// A protocol for types that can be represented as a SwiftSyntax node. -public protocol CodeBlock { +public protocol CodeBlock: PatternConvertible, Sendable { /// The SwiftSyntax representation of the code block. var syntax: SyntaxProtocol { get } @@ -55,4 +55,13 @@ extension CodeBlock { ) -> CodeBlock { FunctionCallExp(base: self, methodName: name, parameters: parameters()) } + + /// The pattern syntax representation of this code block. + public var patternSyntax: PatternSyntax { + let expr = ExprSyntax( + fromProtocol: self.syntax.as(ExprSyntax.self) + ?? DeclReferenceExprSyntax(baseName: .identifier("")) + ) + return PatternSyntax(ExpressionPatternSyntax(expression: expr)) + } } diff --git a/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift b/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift index 317a0d8..920d865 100644 --- a/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift +++ b/Sources/SyntaxKit/Core/ExprCodeBlockBuilder.swift @@ -29,10 +29,9 @@ import SwiftSyntax -/// A result builder that produces exactly one `ExprCodeBlock`. -/// This ensures compile-time type safety for expression-based constructs. +/// A result builder for creating expressions that can be used as code blocks. @resultBuilder -public enum ExprCodeBlockBuilder { +public enum ExprCodeBlockBuilder: Sendable, Equatable { /// Builds a single expression code block from the provided expression. /// - Parameter expression: The expression code block to build. /// - Returns: The expression code block unchanged. diff --git a/Sources/SyntaxKit/Core/Line.swift b/Sources/SyntaxKit/Core/Line.swift index 3017ae6..551dd96 100644 --- a/Sources/SyntaxKit/Core/Line.swift +++ b/Sources/SyntaxKit/Core/Line.swift @@ -30,9 +30,9 @@ import SwiftSyntax /// Represents a single comment line that can be attached to a syntax node. -public struct Line { +public struct Line: Sendable, Equatable { /// The kind of comment line. - public enum Kind { + public enum Kind: Sendable, Equatable { /// Regular line comment that starts with `//`. case line /// Documentation line comment that starts with `///`. diff --git a/Sources/SyntaxKit/Core/PatternConvertible.swift b/Sources/SyntaxKit/Core/PatternConvertible.swift index de8d77e..23cb3e7 100644 --- a/Sources/SyntaxKit/Core/PatternConvertible.swift +++ b/Sources/SyntaxKit/Core/PatternConvertible.swift @@ -31,7 +31,7 @@ import Foundation import SwiftSyntax /// Types that can be turned into a `PatternSyntax` suitable for a `switch` case pattern. -public protocol PatternConvertible { +public protocol PatternConvertible: Sendable { /// SwiftSyntax representation of the pattern. var patternSyntax: PatternSyntax { get } } diff --git a/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift b/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift index 283a065..fb26580 100644 --- a/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift +++ b/Sources/SyntaxKit/Core/PatternConvertibleBuilder.swift @@ -29,10 +29,9 @@ import SwiftSyntax -/// A result builder that produces exactly one `CodeBlock & PatternConvertible`. -/// This ensures compile-time type safety for pattern-based constructs. +/// A result builder for creating pattern-convertible types. @resultBuilder -public enum PatternConvertibleBuilder { +public enum PatternConvertibleBuilder: Sendable, Equatable { /// Builds a single pattern convertible code block from the provided pattern. /// - Parameter pattern: The pattern convertible code block to build. /// - Returns: The pattern convertible code block unchanged. diff --git a/Sources/SyntaxKit/Core/TypeRepresentable.swift b/Sources/SyntaxKit/Core/TypeRepresentable.swift index 13c059a..3c163d6 100644 --- a/Sources/SyntaxKit/Core/TypeRepresentable.swift +++ b/Sources/SyntaxKit/Core/TypeRepresentable.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// A protocol that represents a type that can be converted to SwiftSyntax. -public protocol TypeRepresentable { +/// Types that can be represented as a Swift type. +public protocol TypeRepresentable: Sendable { /// Returns the SwiftSyntax representation of the conforming type. var typeSyntax: TypeSyntax { get } } diff --git a/Sources/SyntaxKit/Declarations/Class.swift b/Sources/SyntaxKit/Declarations/Class.swift index f38ae5e..c91cda9 100644 --- a/Sources/SyntaxKit/Declarations/Class.swift +++ b/Sources/SyntaxKit/Declarations/Class.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `class` declaration. -public struct Class: CodeBlock { +public struct Class: CodeBlock, Sendable { private let name: String private let members: [CodeBlock] private var inheritance: [String] = [] diff --git a/Sources/SyntaxKit/Declarations/Enum.swift b/Sources/SyntaxKit/Declarations/Enum.swift index a8e82c8..b7e551b 100644 --- a/Sources/SyntaxKit/Declarations/Enum.swift +++ b/Sources/SyntaxKit/Declarations/Enum.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `enum` declaration. -public struct Enum: CodeBlock { +public struct Enum: CodeBlock, Sendable { private let name: String private let members: [CodeBlock] private var inheritance: [String] = [] diff --git a/Sources/SyntaxKit/Declarations/Extension.swift b/Sources/SyntaxKit/Declarations/Extension.swift index 1ff7deb..8b1ad90 100644 --- a/Sources/SyntaxKit/Declarations/Extension.swift +++ b/Sources/SyntaxKit/Declarations/Extension.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `extension` declaration. -public struct Extension: CodeBlock { +public struct Extension: CodeBlock, Sendable { private let extendedType: String private let members: [CodeBlock] private var inheritance: [String] = [] diff --git a/Sources/SyntaxKit/Declarations/Import.swift b/Sources/SyntaxKit/Declarations/Import.swift index 37334d1..39b3ace 100644 --- a/Sources/SyntaxKit/Declarations/Import.swift +++ b/Sources/SyntaxKit/Declarations/Import.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `import` declaration. -public struct Import: CodeBlock { +public struct Import: CodeBlock, Sendable { private let moduleName: String private var accessModifier: AccessModifier? private var attributes: [AttributeInfo] = [] diff --git a/Sources/SyntaxKit/Declarations/Init.swift b/Sources/SyntaxKit/Declarations/Init.swift index 400d38a..3407744 100644 --- a/Sources/SyntaxKit/Declarations/Init.swift +++ b/Sources/SyntaxKit/Declarations/Init.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// An initializer expression. -public struct Init: CodeBlock, ExprCodeBlock, LiteralValue, CodeBlockable { +/// A Swift initializer expression. +public struct Init: CodeBlock, ExprCodeBlock, LiteralValue, CodeBlockable, Sendable { private let type: String private let parameters: [ParameterExp] @@ -44,7 +44,7 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue, CodeBlockable { /// Creates an initializer expression. /// - Parameters: /// - type: The type to initialize. - /// - params: A ``ParameterExpBuilder`` that provides the parameters for the initializer. + /// - params: A ``ParameterExpBuilderResult`` that provides the parameters for the initializer. public init(_ type: String, @ParameterExpBuilderResult _ params: () throws -> [ParameterExp]) rethrows { @@ -121,18 +121,18 @@ public struct Init: CodeBlock, ExprCodeBlock, LiteralValue, CodeBlockable { exprSyntax } - /// Calls a method on the initialized object. + /// Calls a method on this initializer. /// - Parameter methodName: The name of the method to call. - /// - Returns: A ``FunctionCallExp`` that represents the method call. + /// - Returns: A code block that represents the method call. public func call(_ methodName: String) -> CodeBlock { FunctionCallExp(base: self, methodName: methodName) } - /// Calls a method on the initialized object with parameters. + /// Calls a method on this initializer with parameters. /// - Parameters: /// - methodName: The name of the method to call. - /// - params: A ``ParameterExpBuilder`` that provides the parameters for the method call. - /// - Returns: A ``FunctionCallExp`` that represents the method call. + /// - params: A ``ParameterExpBuilderResult`` that provides the parameters for the method call. + /// - Returns: A code block that represents the method call. public func call(_ methodName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) -> CodeBlock { diff --git a/Sources/SyntaxKit/Declarations/Protocol.swift b/Sources/SyntaxKit/Declarations/Protocol.swift index 83d2db3..a8708ae 100644 --- a/Sources/SyntaxKit/Declarations/Protocol.swift +++ b/Sources/SyntaxKit/Declarations/Protocol.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `protocol` declaration. -public struct Protocol: CodeBlock { +public struct Protocol: CodeBlock, Sendable { private let name: String private let members: [CodeBlock] private var inheritance: [String] = [] diff --git a/Sources/SyntaxKit/Declarations/Struct.swift b/Sources/SyntaxKit/Declarations/Struct.swift index 82e9135..96ac94a 100644 --- a/Sources/SyntaxKit/Declarations/Struct.swift +++ b/Sources/SyntaxKit/Declarations/Struct.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `struct` declaration. -public struct Struct: CodeBlock { +public struct Struct: CodeBlock, Sendable { private let name: String private let members: [CodeBlock] private var genericParameter: String? diff --git a/Sources/SyntaxKit/Declarations/TypeAlias.swift b/Sources/SyntaxKit/Declarations/TypeAlias.swift index 90b17e0..4d0f077 100644 --- a/Sources/SyntaxKit/Declarations/TypeAlias.swift +++ b/Sources/SyntaxKit/Declarations/TypeAlias.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift `typealias` declaration. -public struct TypeAlias: CodeBlock { +public struct TypeAlias: CodeBlock, Sendable { private let name: String private let existingType: String private var attributes: [AttributeInfo] = [] diff --git a/Sources/SyntaxKit/Documentation.docc/Documentation.md b/Sources/SyntaxKit/Documentation.docc/Documentation.md index cb4a2ca..52ca84b 100644 --- a/Sources/SyntaxKit/Documentation.docc/Documentation.md +++ b/Sources/SyntaxKit/Documentation.docc/Documentation.md @@ -187,40 +187,91 @@ struct BlackjackCard { ## Topics -### Declarations +### Tutorials +- -- ``Struct`` +### Declarations +- ``AccessModifier`` +- ``Class`` +- ``ComputedProperty`` - ``Enum`` -- ``EnumCase`` +- ``Extension`` - ``Function`` -- ``Init`` -- ``ComputedProperty`` -- ``VariableDecl`` +- ``FunctionRequirement`` +- ``Group`` +- ``Import`` - ``Let`` -- ``Variable`` -- ``Extension`` -- ``Class`` +- ``Parameter`` +- ``PropertyRequirement`` - ``Protocol`` +- ``Struct`` - ``Tuple`` - ``TypeAlias`` -- ``Infix`` -- ``PropertyRequirement`` -- ``FunctionRequirement`` +- ``Variable`` +- ``VariableKind`` ### Expressions & Statements - ``Assignment`` +- ``Call`` +- ``CaptureReferenceType`` +- ``Closure`` +- ``ClosureParameter`` +- ``ClosureType`` +- ``ConditionalOp`` +- ``EnumCase`` +- ``Infix`` +- ``Init`` +- ``Line`` +- ``Parenthesized`` +- ``ParameterExp`` - ``PlusAssign`` - ``Return`` - ``VariableExp`` ### Control Flow +- ``Break`` +- ``Case`` +- ``Continue`` +- ``Default`` +- ``Do`` +- ``Fallthrough`` +- ``For`` +- ``Guard`` - ``If`` +- ``Pattern`` - ``Switch`` - ``SwitchCase`` -- ``Default`` +- ``SwitchLet`` +- ``Then`` +- ``While`` + +### Error Handling +- ``Catch`` +- ``Throw`` ### Building Blocks +- ``Attribute`` - ``CodeBlock`` -- ``Parameter`` +- ``EmptyCodeBlock`` - ``Literal`` +### Protocols +- ``CodeBlockable`` +- ``CodeBlockableLiteral`` +- ``DictionaryValue`` +- ``ExprCodeBlock`` +- ``LiteralValue`` +- ``PatternCodeBlock`` +- ``PatternConvertible`` +- ``TypeRepresentable`` + +### Result Builders +- ``CatchBuilder`` +- ``ClosureParameterBuilderResult`` +- ``CodeBlockBuilder`` +- ``CodeBlockBuilderResult`` +- ``CommentBuilderResult`` +- ``ExprCodeBlockBuilder`` +- ``ParameterBuilderResult`` +- ``ParameterExpBuilderResult`` +- ``PatternConvertibleBuilder`` diff --git a/Sources/SyntaxKit/Documentation.docc/Tutorials/Creating-Macros-with-SyntaxKit.md b/Sources/SyntaxKit/Documentation.docc/Tutorials/Creating-Macros-with-SyntaxKit.md new file mode 100644 index 0000000..81de626 --- /dev/null +++ b/Sources/SyntaxKit/Documentation.docc/Tutorials/Creating-Macros-with-SyntaxKit.md @@ -0,0 +1,314 @@ +# Creating Macros with SyntaxKit + +Learn how to create Swift macros using SyntaxKit's declarative syntax. + +## Overview + +This tutorial walks you through creating a simple freestanding expression macro using SyntaxKit. We'll build a `#stringify` macro that takes two expressions and returns a tuple containing their sum and the source code that produced it. + +## Prerequisites + +- Swift 6.1 or later +- Xcode 15.0 or later +- Basic understanding of Swift macros + +## Step 1: Create the Package Structure + +First, create a new Swift package for your macro: + +```bash +mkdir MyMacro +cd MyMacro +swift package init --type library +``` + +## Step 2: Configure Package.swift + +Update your `Package.swift` to include the necessary dependencies and targets: + +```swift +// swift-tools-version: 6.1 +import PackageDescription +import CompilerPluginSupport + +let package = Package( + name: "MyMacro", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .watchOS(.v6), + .tvOS(.v13), + .visionOS(.v1) + ], + products: [ + .library( + name: "MyMacro", + targets: ["MyMacro"] + ), + .executable( + name: "MyMacroClient", + targets: ["MyMacroClient"] + ), + ], + dependencies: [ + .package(url: "https://github.com/your-username/SyntaxKit.git", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-syntax.git", from: "601.0.1") + ], + targets: [ + // Macro implementation + .macro( + name: "MyMacroMacros", + dependencies: [ + .product(name: "SyntaxKit", package: "SyntaxKit"), + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax") + ] + ), + + // Library that exposes the macro + .target(name: "MyMacro", dependencies: ["MyMacroMacros"]), + + // Client executable + .executableTarget(name: "MyMacroClient", dependencies: ["MyMacro"]), + + // Tests + .testTarget( + name: "MyMacroTests", + dependencies: [ + "MyMacroMacros", + .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + ] + ), + ] +) +``` + +## Step 3: Create the Macro Implementation + +Create the file `Sources/MyMacroMacros/StringifyMacro.swift`: + +```swift +import SwiftCompilerPlugin +import SwiftSyntax +import SwiftSyntaxMacros +import SyntaxKit + +/// A freestanding expression macro that takes two expressions and returns +/// a tuple containing their sum and the source code that produced it. +/// +/// For example: +/// ```swift +/// let (result, code) = #stringify(a + b) +/// ``` +/// expands to: +/// ```swift +/// let (result, code) = (a + b, "a + b") +/// ``` +public struct StringifyMacro: ExpressionMacro { + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) -> ExprSyntax { + // Extract the arguments from the macro + let arguments = node.arguments + + // Ensure we have exactly two arguments + guard arguments.count == 2, + let firstArg = arguments.first?.expression, + let secondArg = arguments.last?.expression else { + fatalError("compiler bug: the macro does not have exactly two arguments") + } + + // Build the result using SyntaxKit's declarative syntax + return Tuple { + // First element: the sum of the two expressions + try Infix("+") { + VariableExp(firstArg.description) + VariableExp(secondArg.description) + } + + // Second element: the source code as a string literal + Literal.string("\(firstArg.description) + \(secondArg.description)") + }.expr + } +} +``` + +## Step 4: Create the Macro Plugin + +Create the file `Sources/MyMacroMacros/MacroPlugin.swift`: + +```swift +import SwiftCompilerPlugin +import SwiftSyntaxMacros + +@main +struct MyMacroPlugin: CompilerPlugin { + let providingMacros: [Macro.Type] = [ + StringifyMacro.self, + ] +} +``` + +## Step 5: Create the Public API + +Create the file `Sources/MyMacro/MyMacro.swift`: + +```swift +/// A freestanding expression macro that takes two expressions and returns +/// a tuple containing their sum and the source code that produced it. +/// +/// ## Example +/// ```swift +/// let a = 17 +/// let b = 25 +/// let (result, code) = #stringify(a, b) +/// // result = 42, code = "a + b" +/// ``` +@freestanding(expression) +public macro stringify(_ first: Any, _ second: Any) -> (Any, String) = #externalMacro( + module: "MyMacroMacros", + type: "StringifyMacro" +) +``` + +## Step 6: Create a Client Example + +Create the file `Sources/MyMacroClient/main.swift`: + +```swift +import MyMacro + +let a = 17 +let b = 25 + +let (result, code) = #stringify(a, b) + +print("The value \(result) was produced by the code \"\(code)\"") +// Output: The value 42 was produced by the code "a + b" +``` + +## Step 7: Test Your Macro + +Create the file `Tests/MyMacroTests/StringifyMacroTests.swift`: + +```swift +import XCTest +import SwiftSyntaxMacros +import SwiftSyntaxMacrosTestSupport +@testable import MyMacroMacros + +final class StringifyMacroTests: XCTestCase { + func testStringifyMacro() { + assertMacroExpansion( + """ + let (result, code) = #stringify(a, b) + """, + expandedSource: """ + let (result, code) = (a + b, "a + b") + """, + macros: testMacros + ) + } + + func testStringifyMacroWithLiterals() { + assertMacroExpansion( + """ + let (result, code) = #stringify(5, 3) + """, + expandedSource: """ + let (result, code) = (5 + 3, "5 + 3") + """, + macros: testMacros + ) + } +} + +let testMacros: [String: Macro.Type] = [ + "stringify": StringifyMacro.self, +] +``` + +## Step 8: Build and Run + +Build your macro package: + +```bash +swift build +``` + +Run the client example: + +```bash +swift run MyMacroClient +``` + +## How It Works + +1. **Macro Declaration**: The `@freestanding(expression)` attribute tells Swift that this is a freestanding expression macro. + +2. **Macro Implementation**: The `StringifyMacro` struct implements the `ExpressionMacro` protocol, which requires an `expansion` method. + +3. **SyntaxKit Integration**: Instead of manually building SwiftSyntax nodes, we use SyntaxKit's declarative syntax: + - `Tuple { ... }` creates a tuple expression + - `Infix("+") { ... }` creates an infix operator expression + - `VariableExp(...)` creates a variable expression + - `Literal.string(...)` creates a string literal + +4. **Code Generation**: The macro expands `#stringify(a, b)` into `(a + b, "a + b")`. + +## Advanced Example: Extension Macro + +You can also create extension macros using SyntaxKit. Here's a simple example: + +```swift +import SwiftCompilerPlugin +import SwiftSyntax +import SwiftSyntaxMacros +import SyntaxKit + +public struct AddDescriptionMacro: ExtensionMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo declaration: some DeclGroupSyntax, + providingExtensionsOf type: some TypeSyntaxProtocol, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [ExtensionDeclSyntax] { + + // Get the type name + let typeName = declaration.as(StructDeclSyntax.self)?.name ?? + declaration.as(ClassDeclSyntax.self)?.name ?? + declaration.as(EnumDeclSyntax.self)?.name + + guard let typeName else { + throw MacroError("Macro can only be applied to structs, classes, or enums") + } + + // Create an extension that adds a description property + let extensionDecl = Extension(typeName.trimmed.text) { + ComputedProperty("description") { + Return { + Literal.string("\(typeName.trimmed.text) instance") + } + } + }.inherits("CustomStringConvertible") + + return [extensionDecl.syntax.as(ExtensionDeclSyntax.self)!] + } +} + +enum MacroError: Error { + case error(String) +} +``` + + +## See Also + +- ``Struct`` +- ``Enum`` +- ``Variable`` +- ``Function`` +- ``Extension`` +- ``ComputedProperty`` \ No newline at end of file diff --git a/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift b/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift index 0e05237..c9285ad 100644 --- a/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift +++ b/Sources/SyntaxKit/ErrorHandling/CatchBuilder.swift @@ -77,7 +77,7 @@ import SwiftSyntax /// The builder produces `CatchClauseListSyntax` which is directly compatible with SwiftSyntax's /// `DoStmtSyntax`, enabling seamless integration with the Swift compiler's syntax tree. @resultBuilder -public enum CatchBuilder { +public enum CatchBuilder: Sendable, Equatable { /// Combines multiple catch clauses into a `CatchClauseListSyntax`. /// /// This method is called by the result builder when multiple catch clauses are provided diff --git a/Sources/SyntaxKit/Expressions/Call.swift b/Sources/SyntaxKit/Expressions/Call.swift index 8154697..4a77ed3 100644 --- a/Sources/SyntaxKit/Expressions/Call.swift +++ b/Sources/SyntaxKit/Expressions/Call.swift @@ -46,7 +46,7 @@ public struct Call: CodeBlock { /// Creates a global function call expression with parameters. /// - Parameters: /// - functionName: The name of the function to call. - /// - params: A ``ParameterExpBuilder`` that provides the parameters for the function call. + /// - params: A ``ParameterExpBuilderResult`` that provides the parameters for the function call. public init( _ functionName: String, @ParameterExpBuilderResult _ params: () throws -> [ParameterExp] ) rethrows { diff --git a/Sources/SyntaxKit/Expressions/Closure+Capture.swift b/Sources/SyntaxKit/Expressions/Closure+Capture.swift index 864ec10..5b52366 100644 --- a/Sources/SyntaxKit/Expressions/Closure+Capture.swift +++ b/Sources/SyntaxKit/Expressions/Closure+Capture.swift @@ -54,7 +54,7 @@ private struct CaptureInfo { } else { self.name = .identifier("self") // fallback #warning( - "TODO: Review fallback for non-VariableExp capture expression - consider if this should be an error instead" + "TODO: Review fallback for non-VariableExp capture expression" ) } } @@ -67,7 +67,7 @@ private struct CaptureInfo { } else { self.name = .identifier("self") // fallback #warning( - "TODO: Review fallback for non-VariableExp parameter value - consider if this should be an error instead" + "TODO: Review fallback for non-VariableExp parameter value" ) } } diff --git a/Sources/SyntaxKit/Expressions/Closure.swift b/Sources/SyntaxKit/Expressions/Closure.swift index e5b3ee8..c8ea670 100644 --- a/Sources/SyntaxKit/Expressions/Closure.swift +++ b/Sources/SyntaxKit/Expressions/Closure.swift @@ -43,8 +43,8 @@ public struct Closure: CodeBlock { /// Creates a closure with all parameters. /// - Parameters: - /// - capture: A ``ParameterExpBuilder`` that provides the capture list. - /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - capture: A ``ParameterExpBuilderResult`` that provides the capture list. + /// - parameters: A ``ClosureParameterBuilderResult`` that provides the closure parameters. /// - returnType: The return type of the closure. /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( @@ -61,8 +61,8 @@ public struct Closure: CodeBlock { /// Creates a closure without a return type. /// - Parameters: - /// - capture: A ``ParameterExpBuilder`` that provides the capture list. - /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - capture: A ``ParameterExpBuilderResult`` that provides the capture list. + /// - parameters: A ``ClosureParameterBuilderResult`` that provides the closure parameters. /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( @ParameterExpBuilderResult capture: () -> [ParameterExp], @@ -74,7 +74,7 @@ public struct Closure: CodeBlock { /// Creates a closure without parameters. /// - Parameters: - /// - capture: A ``ParameterExpBuilder`` that provides the capture list. + /// - capture: A ``ParameterExpBuilderResult`` that provides the capture list. /// - returnType: The return type of the closure. /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( @@ -92,7 +92,7 @@ public struct Closure: CodeBlock { /// Creates a closure without parameters and return type. /// - Parameters: - /// - capture: A ``ParameterExpBuilder`` that provides the capture list. + /// - capture: A ``ParameterExpBuilderResult`` that provides the capture list. /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( @ParameterExpBuilderResult capture: () -> [ParameterExp], @@ -108,7 +108,7 @@ public struct Closure: CodeBlock { /// Creates a closure without capture list and return type. /// - Parameters: - /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - parameters: A ``ClosureParameterBuilderResult`` that provides the closure parameters. /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( @ClosureParameterBuilderResult parameters: () -> [ClosureParameter], @@ -124,7 +124,7 @@ public struct Closure: CodeBlock { /// Creates a closure without capture list. /// - Parameters: - /// - parameters: A ``ClosureParameterBuilder`` that provides the closure parameters. + /// - parameters: A ``ClosureParameterBuilderResult`` that provides the closure parameters. /// - returnType: The return type of the closure. /// - body: A ``CodeBlockBuilder`` that provides the body of the closure. public init( diff --git a/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift b/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift index 8cb24c5..f0af279 100644 --- a/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift +++ b/Sources/SyntaxKit/Expressions/ClosureParameterBuilderResult.swift @@ -29,7 +29,7 @@ /// A result builder for creating closure parameter lists. @resultBuilder -public enum ClosureParameterBuilderResult { +public enum ClosureParameterBuilderResult: Sendable, Equatable { /// Builds a block of closure parameters. /// - Parameter components: The closure parameters to combine. /// - Returns: An array of closure parameters. diff --git a/Sources/SyntaxKit/Expressions/ClosureType.swift b/Sources/SyntaxKit/Expressions/ClosureType.swift index d20dbcc..97dab83 100644 --- a/Sources/SyntaxKit/Expressions/ClosureType.swift +++ b/Sources/SyntaxKit/Expressions/ClosureType.swift @@ -36,7 +36,7 @@ public struct ClosureType: CodeBlock, TypeRepresentable { private var attributes: [AttributeInfo] = [] /// Creates a closure type with no parameters. - /// - Parameter returns: The return type of the closure. + /// - Parameter returnType: The return type of the closure. public init(returns returnType: String? = nil) { self.parameters = [] self.returnType = returnType @@ -44,9 +44,9 @@ public struct ClosureType: CodeBlock, TypeRepresentable { /// Creates a closure type with parameters. /// - Parameters: - /// - returns: The return type of the closure. + /// - returnType: The return type of the closure. /// - parameters: A ``ClosureParameterBuilderResult`` that provides the parameters. - internal init( + public init( returns returnType: String? = nil, @ClosureParameterBuilderResult _ parameters: () -> [ClosureParameter] ) { diff --git a/Sources/SyntaxKit/Expressions/ConditionalOp.swift b/Sources/SyntaxKit/Expressions/ConditionalOp.swift index 6e3d416..ef85738 100644 --- a/Sources/SyntaxKit/Expressions/ConditionalOp.swift +++ b/Sources/SyntaxKit/Expressions/ConditionalOp.swift @@ -37,9 +37,9 @@ public struct ConditionalOp: CodeBlock { /// Creates a ternary conditional operator expression. /// - Parameters: - /// - if: The condition expression. - /// - then: The expression to evaluate if the condition is true. - /// - else: The expression to evaluate if the condition is false. + /// - condition: The condition expression. + /// - thenExpression: The expression to evaluate if the condition is true. + /// - elseExpression: The expression to evaluate if the condition is false. public init( if condition: CodeBlock, then thenExpression: CodeBlock, diff --git a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift index 78753d5..76fb4f2 100644 --- a/Sources/SyntaxKit/Expressions/FunctionCallExp.swift +++ b/Sources/SyntaxKit/Expressions/FunctionCallExp.swift @@ -30,14 +30,14 @@ import SwiftSyntax /// An expression that calls a function. -public struct FunctionCallExp: CodeBlock { +internal struct FunctionCallExp: CodeBlock { internal let baseName: String internal let methodName: String internal let parameters: [ParameterExp] private let base: CodeBlock? /// Creates a function call expression on a variable name. - public init(baseName: String, methodName: String) { + internal init(baseName: String, methodName: String) { self.baseName = baseName self.methodName = methodName self.parameters = [] @@ -45,7 +45,7 @@ public struct FunctionCallExp: CodeBlock { } /// Creates a function call expression with parameters on a variable name. - public init(baseName: String, methodName: String, parameters: [ParameterExp]) { + internal init(baseName: String, methodName: String, parameters: [ParameterExp]) { self.baseName = baseName self.methodName = methodName self.parameters = parameters @@ -53,14 +53,14 @@ public struct FunctionCallExp: CodeBlock { } /// Creates a function call expression on an arbitrary base expression. - public init(base: CodeBlock, methodName: String, parameters: [ParameterExp] = []) { + internal init(base: CodeBlock, methodName: String, parameters: [ParameterExp] = []) { self.baseName = "" self.methodName = methodName self.parameters = parameters self.base = base } - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { let baseExpr: ExprSyntax if let base = base { if let exprSyntax = base.syntax.as(ExprSyntax.self) { diff --git a/Sources/SyntaxKit/Expressions/Literal+Convenience.swift b/Sources/SyntaxKit/Expressions/Literal+Convenience.swift index b7c024f..85c9de2 100644 --- a/Sources/SyntaxKit/Expressions/Literal+Convenience.swift +++ b/Sources/SyntaxKit/Expressions/Literal+Convenience.swift @@ -43,10 +43,10 @@ extension Literal { } /// Converts a Literal.tuple to a TupleLiteral for use in Variable declarations. - public var asTupleLiteral: TupleLiteral? { + public var asTupleLiteral: CodeBlockableLiteral? { switch self { case .tuple(let elements): - return TupleLiteral(elements) + return TupleLiteralArray(elements) default: return nil } diff --git a/Sources/SyntaxKit/Expressions/Literal.swift b/Sources/SyntaxKit/Expressions/Literal.swift index 96ae3bc..7a8388b 100644 --- a/Sources/SyntaxKit/Expressions/Literal.swift +++ b/Sources/SyntaxKit/Expressions/Literal.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// A literal value. -public enum Literal: CodeBlock, CodeBlockable { +/// Represents Swift literal values. +public enum Literal: CodeBlock, CodeBlockable, Sendable { /// A string literal. case string(String) /// A floating-point literal. @@ -63,6 +63,7 @@ public enum Literal: CodeBlock, CodeBlockable { case .integer: return "Int" case .nil: return "Any?" case .boolean: return "Bool" + // TODO: Consider more specific type inference for ref cases case .ref: return "Any" case .tuple(let elements): let elementTypes = elements.map { element in @@ -73,7 +74,9 @@ public enum Literal: CodeBlock, CodeBlockable { case .string: return "String" case .boolean: return "Bool" case .nil: return "Any?" + // TODO: Consider more specific type inference for ref cases case .ref: return "Any" + // TODO: Consider more specific type inference for complex literals case .tuple: return "Any" case .array: return "Any" case .dictionary: return "Any" @@ -85,12 +88,14 @@ public enum Literal: CodeBlock, CodeBlockable { return "(\(elementTypes.joined(separator: ", ")))" case .array(let elements): if elements.isEmpty { + // TODO: Consider more specific type inference for empty arrays return "[Any]" } let elementType = elements.first?.typeName ?? "Any" return "[\(elementType)]" case .dictionary(let elements): if elements.isEmpty { + // TODO: Consider more specific type inference for empty dictionaries return "[Any: Any]" } let keyType = elements.first?.0.typeName ?? "Any" diff --git a/Sources/SyntaxKit/Expressions/LiteralValue.swift b/Sources/SyntaxKit/Expressions/LiteralValue.swift index afb8cfe..0cb6776 100644 --- a/Sources/SyntaxKit/Expressions/LiteralValue.swift +++ b/Sources/SyntaxKit/Expressions/LiteralValue.swift @@ -30,7 +30,7 @@ import Foundation /// A protocol for types that can be represented as literal values in Swift code. -public protocol LiteralValue { +public protocol LiteralValue: Sendable { /// The Swift type name for this literal value. var typeName: String { get } diff --git a/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift b/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift index 1297506..77b1bcf 100644 --- a/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift +++ b/Sources/SyntaxKit/Expressions/NegatedPropertyAccessExp.swift @@ -29,22 +29,22 @@ import SwiftSyntax -/// An expression that negates a property access. -public struct NegatedPropertyAccessExp: CodeBlock, ExprCodeBlock { +/// An expression that negates property access. +internal struct NegatedPropertyAccessExp: CodeBlock, ExprCodeBlock { internal let base: CodeBlock /// Creates a negated property access expression. /// - Parameter base: The base property access expression. - public init(base: CodeBlock) { + internal init(base: CodeBlock) { self.base = base } /// Backward compatibility initializer for (baseName, propertyName). - public init(baseName: String, propertyName: String) { + internal init(baseName: String, propertyName: String) { self.base = PropertyAccessExp(baseName: baseName, propertyName: propertyName) } - public var exprSyntax: ExprSyntax { + internal var exprSyntax: ExprSyntax { let memberAccess = base.syntax.as(ExprSyntax.self) ?? ExprSyntax( @@ -62,7 +62,7 @@ public struct NegatedPropertyAccessExp: CodeBlock, ExprCodeBlock { ) } - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { exprSyntax } } diff --git a/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift b/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift index 36925a2..65d9c27 100644 --- a/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift +++ b/Sources/SyntaxKit/Expressions/OptionalChainingExp.swift @@ -29,33 +29,28 @@ import SwiftSyntax -/// A Swift optional chaining expression (e.g., `self?`). -public struct OptionalChainingExp: CodeBlock { - private let base: CodeBlock +/// An expression that performs optional chaining. +internal struct OptionalChainingExp: CodeBlock { + internal let base: CodeBlock /// Creates an optional chaining expression. /// - Parameter base: The base expression to make optional. - public init(base: CodeBlock) { + internal init(base: CodeBlock) { self.base = base } - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { // Convert base.syntax to ExprSyntax more safely let baseExpr: ExprSyntax - if let exprSyntax = base.syntax.as(ExprSyntax.self) { - baseExpr = exprSyntax + if let expr = base.syntax.as(ExprSyntax.self) { + baseExpr = expr } else { // Fallback to a default expression if conversion fails #warning( - "TODO: Review fallback for failed expression conversion - consider if this should be an error instead" + "TODO: Review fallback for failed expression conversion" ) baseExpr = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(""))) } - - // Add optional chaining operator - return PostfixOperatorExprSyntax( - expression: baseExpr, - operator: .postfixOperator("?", trailingTrivia: []) - ) + return OptionalChainingExprSyntax(expression: baseExpr) } } diff --git a/Sources/SyntaxKit/Expressions/PlusAssign.swift b/Sources/SyntaxKit/Expressions/PlusAssign.swift index 8572b81..9ac07b9 100644 --- a/Sources/SyntaxKit/Expressions/PlusAssign.swift +++ b/Sources/SyntaxKit/Expressions/PlusAssign.swift @@ -30,38 +30,63 @@ import SwiftSyntax /// A `+=` expression. +/// +/// **Deprecated**: Use `Infix(target, "+=", value)` instead. This type will be removed in a future version. +@available( + *, deprecated, + message: + "Use Infix(target, \"+=\", value) instead. This type will be removed in a future version." +) public struct PlusAssign: CodeBlock { private let target: String private let valueExpr: ExprSyntax /// Creates a `+=` expression with an expression value. + /// + /// **Deprecated**: Use `Infix(target, "+=", value)` instead. + @available(*, deprecated, message: "Use Infix(target, \"+=\", value) instead.") public init(_ target: String, _ value: any ExprCodeBlock) { self.target = target self.valueExpr = value.exprSyntax } /// Creates a `+=` expression with a literal value. + /// + /// **Deprecated**: Use `Infix(target, "+=", value)` instead. + @available(*, deprecated, message: "Use Infix(target, \"+=\", value) instead.") public init(_ target: String, _ literal: Literal) { self.target = target self.valueExpr = literal.exprSyntax } /// Creates a `+=` expression with an integer literal value. + /// + /// **Deprecated**: Use `Infix(target, "+=", value)` instead. + @available(*, deprecated, message: "Use Infix(target, \"+=\", value) instead.") public init(_ target: String, _ value: Int) { self.init(target, .integer(value)) } /// Creates a `+=` expression with a string literal value. + /// + /// **Deprecated**: Use `Infix(target, "+=", value)` instead. + @available(*, deprecated, message: "Use Infix(target, \"+=\", value) instead.") public init(_ target: String, _ value: String) { self.init(target, .string(value)) } /// Creates a `+=` expression with a boolean literal value. + /// + /// **Deprecated**: Use `Infix(target, "+=", value)` instead. + @available(*, deprecated, message: "Use Infix(target, \"+=\", value) instead.") public init(_ target: String, _ value: Bool) { self.init(target, .boolean(value)) } /// Creates a `+=` expression with a double literal value. + /// + /// **Deprecated**: Use `Infix(target, "+=", value)` instead. + @available(*, deprecated, message: "Use Infix(target, \"+=\", value) instead.") public init(_ target: String, _ value: Double) { self.init(target, .float(value)) } diff --git a/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift b/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift index ad0d488..146a141 100644 --- a/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift +++ b/Sources/SyntaxKit/Expressions/PropertyAccessExp.swift @@ -29,8 +29,8 @@ import SwiftSyntax -/// An expression that accesses a property on a base expression. -public struct PropertyAccessExp: CodeBlock, ExprCodeBlock { +/// An expression that accesses a property. +internal struct PropertyAccessExp: CodeBlock, ExprCodeBlock, PropertyAccessible { internal let base: CodeBlock internal let propertyName: String @@ -38,31 +38,31 @@ public struct PropertyAccessExp: CodeBlock, ExprCodeBlock { /// - Parameters: /// - base: The base expression. /// - propertyName: The name of the property to access. - public init(base: CodeBlock, propertyName: String) { + internal init(base: CodeBlock, propertyName: String) { self.base = base self.propertyName = propertyName } /// Convenience initializer for backward compatibility (baseName as String). - public init(baseName: String, propertyName: String) { + internal init(baseName: String, propertyName: String) { self.base = VariableExp(baseName) self.propertyName = propertyName } /// Accesses a property on the current property access expression (chaining). /// - Parameter propertyName: The name of the next property to access. - /// - Returns: A new ``PropertyAccessExp`` representing the chained property access. - public func property(_ propertyName: String) -> PropertyAccessExp { + /// - Returns: A property accessible code block representing the chained property access. + internal func property(_ propertyName: String) -> PropertyAccessible { PropertyAccessExp(base: self, propertyName: propertyName) } /// Negates the property access expression. /// - Returns: A negated property access expression. - public func not() -> CodeBlock { + internal func not() -> CodeBlock { NegatedPropertyAccessExp(base: self) } - public var exprSyntax: ExprSyntax { + internal var exprSyntax: ExprSyntax { let baseSyntax = base.syntax.as(ExprSyntax.self) ?? ExprSyntax( @@ -78,7 +78,7 @@ public struct PropertyAccessExp: CodeBlock, ExprCodeBlock { ) } - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { exprSyntax } } diff --git a/Sources/SyntaxKit/Expressions/PropertyAccessible.swift b/Sources/SyntaxKit/Expressions/PropertyAccessible.swift new file mode 100644 index 0000000..2557996 --- /dev/null +++ b/Sources/SyntaxKit/Expressions/PropertyAccessible.swift @@ -0,0 +1,40 @@ +// +// PropertyAccessible.swift +// SyntaxKit +// +// Created by Leo Dion. +// Copyright © 2025 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// A protocol for types that can access properties. +public protocol PropertyAccessible: CodeBlock, Sendable { + /// Accesses a property on the current property access expression (chaining). + /// - Parameter propertyName: The name of the next property to access. + /// - Returns: A property accessible code block representing the chained property access. + func property(_ propertyName: String) -> PropertyAccessible + + /// Negates the property access expression. + /// - Returns: A negated property access expression. + func not() -> CodeBlock +} diff --git a/Sources/SyntaxKit/Expressions/ReferenceExp.swift b/Sources/SyntaxKit/Expressions/ReferenceExp.swift index ad017be..bbc4658 100644 --- a/Sources/SyntaxKit/Expressions/ReferenceExp.swift +++ b/Sources/SyntaxKit/Expressions/ReferenceExp.swift @@ -30,7 +30,7 @@ import SwiftSyntax /// A Swift reference expression (e.g., `weak self`, `unowned self`). -public struct ReferenceExp: CodeBlock { +internal struct ReferenceExp: CodeBlock { private let base: CodeBlock private let referenceType: CaptureReferenceType @@ -38,12 +38,12 @@ public struct ReferenceExp: CodeBlock { /// - Parameters: /// - base: The base expression to reference. /// - referenceType: The type of reference. - public init(base: CodeBlock, referenceType: CaptureReferenceType) { + internal init(base: CodeBlock, referenceType: CaptureReferenceType) { self.base = base self.referenceType = referenceType } - public var syntax: SyntaxProtocol { + internal var syntax: SyntaxProtocol { // For capture lists, we need to create a proper reference // This will be handled by the Closure syntax when used in capture lists let baseExpr: ExprSyntax diff --git a/Sources/SyntaxKit/Expressions/Task.swift b/Sources/SyntaxKit/Expressions/Task.swift deleted file mode 100644 index 9775b78..0000000 --- a/Sources/SyntaxKit/Expressions/Task.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// Task.swift -// SyntaxKit -// -// Created by Leo Dion. -// Copyright © 2025 BrightDigit. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -import SwiftSyntax - -/// A Swift Task expression for structured concurrency. -public struct Task: CodeBlock { - private let body: [CodeBlock] - private var attributes: [AttributeInfo] = [] - - /// Creates a Task block. - /// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the Task. - public init(@CodeBlockBuilderResult _ content: () throws -> [CodeBlock]) rethrows { - self.body = try content() - } - - /// Adds an attribute to the task. - /// - Parameters: - /// - attribute: The attribute name (without the @ symbol). - /// - arguments: The arguments for the attribute, if any. - /// - Returns: A copy of the task with the attribute added. - public func attribute(_ attribute: String, arguments: [String] = []) -> Self { - var copy = self - copy.attributes.append(AttributeInfo(name: attribute, arguments: arguments)) - return copy - } - - public var syntax: SyntaxProtocol { - let bodyBlock = CodeBlockSyntax( - leftBrace: .leftBraceToken(leadingTrivia: .space, trailingTrivia: .newline), - statements: CodeBlockItemListSyntax( - body.compactMap { block in - var item: CodeBlockItemSyntax? - if let decl = block.syntax.as(DeclSyntax.self) { - item = CodeBlockItemSyntax(item: .decl(decl)) - } else if let expr = block.syntax.as(ExprSyntax.self) { - item = CodeBlockItemSyntax(item: .expr(expr)) - } else if let stmt = block.syntax.as(StmtSyntax.self) { - item = CodeBlockItemSyntax(item: .stmt(stmt)) - } - return item?.with(\.trailingTrivia, .newline) - } - ), - rightBrace: .rightBraceToken(leadingTrivia: .newline) - ) - - let taskExpr = FunctionCallExprSyntax( - calledExpression: ExprSyntax( - DeclReferenceExprSyntax(baseName: .identifier("Task")) - ), - leftParen: .leftParenToken(), - arguments: LabeledExprListSyntax([ - LabeledExprSyntax( - label: nil, - colon: nil, - expression: ExprSyntax( - ClosureExprSyntax( - signature: nil, - statements: bodyBlock.statements - ) - ) - ) - ]), - rightParen: .rightParenToken() - ) - - // Add attributes if present - if !attributes.isEmpty { - // For now, just return the task expression without attributes - // since AttributedExprSyntax is not available - return ExprSyntax(taskExpr) - } else { - return ExprSyntax(taskExpr) - } - } -} diff --git a/Sources/SyntaxKit/Functions/Function+Effects.swift b/Sources/SyntaxKit/Functions/Function+Effects.swift index ff6766c..f7a1a9c 100644 --- a/Sources/SyntaxKit/Functions/Function+Effects.swift +++ b/Sources/SyntaxKit/Functions/Function+Effects.swift @@ -41,7 +41,7 @@ extension Function { } /// Marks the function as `throws` or `rethrows`. - /// - Parameter rethrows: Pass `true` to emit `rethrows` instead of `throws`. + /// - Parameter isRethrows: Pass `true` to emit `rethrows` instead of `throws`. public func `throws`(isRethrows: Bool = false) -> Self { var copy = self switch effect { @@ -74,7 +74,7 @@ extension Function { } /// Marks the function as `async throws` or `async rethrows`. - /// - Parameter rethrows: Pass `true` to emit `async rethrows`. + /// - Parameter isRethrows: Pass `true` to emit `async rethrows`. public func asyncThrows(isRethrows: Bool = false) -> Self { var copy = self copy.effect = .asyncThrows(isRethrows: isRethrows, errorType: nil) diff --git a/Sources/SyntaxKit/Functions/Function.swift b/Sources/SyntaxKit/Functions/Function.swift index 0d1e798..ac7e9e5 100644 --- a/Sources/SyntaxKit/Functions/Function.swift +++ b/Sources/SyntaxKit/Functions/Function.swift @@ -60,7 +60,7 @@ public struct Function: CodeBlock { /// - Parameters: /// - name: The name of the function. /// - returnType: The return type of the function, if any. - /// - params: A ``ParameterBuilder`` that provides the parameters of the function. + /// - params: A ``ParameterBuilderResult`` that provides the parameters of the function. /// - content: A ``CodeBlockBuilder`` that provides the body of the function. public init( _ name: String, @@ -77,7 +77,7 @@ public struct Function: CodeBlock { /// Creates a `func` declaration with parameters and body using the DSL syntax. /// - Parameters: /// - name: The name of the function. - /// - params: A ``ParameterBuilder`` that provides the parameters of the function. + /// - params: A ``ParameterBuilderResult`` that provides the parameters of the function. /// - body: A ``CodeBlockBuilder`` that provides the body of the function. public init( _ name: String, diff --git a/Sources/SyntaxKit/Parameters/ParameterBuilderResult.swift b/Sources/SyntaxKit/Parameters/ParameterBuilderResult.swift index 43c641e..4a480ca 100644 --- a/Sources/SyntaxKit/Parameters/ParameterBuilderResult.swift +++ b/Sources/SyntaxKit/Parameters/ParameterBuilderResult.swift @@ -31,7 +31,7 @@ import Foundation /// A result builder for creating arrays of ``Parameter``s. @resultBuilder -public enum ParameterBuilderResult { +public enum ParameterBuilderResult: Sendable, Equatable { /// Builds a block of ``Parameter``s. public static func buildBlock(_ components: Parameter...) -> [Parameter] { components diff --git a/Sources/SyntaxKit/Parameters/ParameterExpBuilderResult.swift b/Sources/SyntaxKit/Parameters/ParameterExpBuilderResult.swift index ef98f12..855a969 100644 --- a/Sources/SyntaxKit/Parameters/ParameterExpBuilderResult.swift +++ b/Sources/SyntaxKit/Parameters/ParameterExpBuilderResult.swift @@ -31,7 +31,7 @@ import Foundation /// A result builder for creating arrays of ``ParameterExp``s. @resultBuilder -public enum ParameterExpBuilderResult { +public enum ParameterExpBuilderResult: Sendable, Equatable { /// Builds a block of ``ParameterExp``s. public static func buildBlock(_ components: ParameterExp...) -> [ParameterExp] { components diff --git a/Sources/SyntaxKit/Parser/SyntaxType.swift b/Sources/SyntaxKit/Parser/SyntaxType.swift index 716b27d..81b9761 100644 --- a/Sources/SyntaxKit/Parser/SyntaxType.swift +++ b/Sources/SyntaxKit/Parser/SyntaxType.swift @@ -29,7 +29,7 @@ import Foundation -internal enum SyntaxType: String, Codable { +internal enum SyntaxType: String, Codable, Equatable { case decl case expr case pattern diff --git a/Sources/SyntaxKit/Patterns/LetBindingPattern.swift b/Sources/SyntaxKit/Patterns/LetBindingPattern.swift index d9f3f5a..9bbf7f4 100644 --- a/Sources/SyntaxKit/Patterns/LetBindingPattern.swift +++ b/Sources/SyntaxKit/Patterns/LetBindingPattern.swift @@ -36,13 +36,13 @@ public enum Pattern { /// Creates a `let` binding pattern for switch cases. /// - Parameter identifier: The name of the variable to bind. /// - Returns: A pattern that binds the value to the given identifier. - public static func `let`(_ identifier: String) -> LetBindingPattern { + public static func `let`(_ identifier: String) -> any PatternConvertible { LetBindingPattern(identifier: identifier) } } /// A `let` binding pattern for switch cases. -public struct LetBindingPattern: PatternConvertible { +internal struct LetBindingPattern: PatternConvertible { private let identifier: String internal init(identifier: String) { @@ -50,7 +50,7 @@ public struct LetBindingPattern: PatternConvertible { } /// SwiftSyntax representation of the let binding pattern. - public var patternSyntax: PatternSyntax { + internal var patternSyntax: PatternSyntax { PatternSyntax( ValueBindingPatternSyntax( bindingSpecifier: .keyword(.let, trailingTrivia: .space), diff --git a/Sources/SyntaxKit/Utilities/CodeBlockable.swift b/Sources/SyntaxKit/Utilities/CodeBlockable.swift index c9a406b..ecb89a3 100644 --- a/Sources/SyntaxKit/Utilities/CodeBlockable.swift +++ b/Sources/SyntaxKit/Utilities/CodeBlockable.swift @@ -28,7 +28,7 @@ // /// Can export a `CodeBlock`. -public protocol CodeBlockable { +public protocol CodeBlockable: Sendable { /// Returns a `CodeBlock`. var codeBlock: CodeBlock { get } } diff --git a/Sources/SyntaxKit/Utilities/CommentBuilderResult.swift b/Sources/SyntaxKit/Utilities/CommentBuilderResult.swift index 609be94..c7f3918 100644 --- a/Sources/SyntaxKit/Utilities/CommentBuilderResult.swift +++ b/Sources/SyntaxKit/Utilities/CommentBuilderResult.swift @@ -29,7 +29,7 @@ /// A result builder for creating arrays of ``Line``s for comments. @resultBuilder -public enum CommentBuilderResult { +public enum CommentBuilderResult: Sendable, Equatable { /// Builds a block of ``Line``s. public static func buildBlock(_ components: Line...) -> [Line] { components } } diff --git a/Sources/SyntaxKit/Utilities/PropertyRequirement.swift b/Sources/SyntaxKit/Utilities/PropertyRequirement.swift index 0a41fb1..b98db43 100644 --- a/Sources/SyntaxKit/Utilities/PropertyRequirement.swift +++ b/Sources/SyntaxKit/Utilities/PropertyRequirement.swift @@ -32,7 +32,7 @@ import SwiftSyntax /// A property requirement inside a protocol declaration. public struct PropertyRequirement: CodeBlock { /// The accessor options for the property. - public enum Access { + public enum Access: Sendable { case get case getSet } diff --git a/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift b/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift index 3b4224e..7f40d12 100644 --- a/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift +++ b/Sources/SyntaxKit/Variables/Variable+LiteralInitializers.swift @@ -36,7 +36,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: A literal value that conforms to ``LiteralValue``. + /// - value: A literal value that conforms to ``LiteralValue``. public init( _ kind: VariableKind, name: String, equals value: T ) { @@ -53,7 +53,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: A string literal value. + /// - value: A string literal value. public init( _ kind: VariableKind, name: String, equals value: String ) { @@ -70,7 +70,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: An integer literal value. + /// - value: An integer literal value. public init( _ kind: VariableKind, name: String, equals value: Int ) { @@ -87,7 +87,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: A boolean literal value. + /// - value: A boolean literal value. public init( _ kind: VariableKind, name: String, equals value: Bool ) { @@ -104,7 +104,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: A double literal value. + /// - value: A double literal value. public init( _ kind: VariableKind, name: String, equals value: Double ) { @@ -121,7 +121,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: A Literal value. + /// - value: A Literal value. public init( _ kind: VariableKind, name: String, equals value: Literal ) { diff --git a/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift b/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift index e295ce1..dc8b620 100644 --- a/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift +++ b/Sources/SyntaxKit/Variables/Variable+TypedInitializers.swift @@ -37,7 +37,7 @@ extension Variable { /// - Parameters: /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. - /// - equals: An Init expression. + /// - defaultValue: An Init expression. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, @@ -59,7 +59,7 @@ extension Variable { /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable. - /// - equals: The initial value expression of the variable, if any. + /// - defaultValue: The initial value expression of the variable, if any. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, @@ -83,7 +83,7 @@ extension Variable { /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable. - /// - equals: A string literal value. + /// - value: A string literal value. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, @@ -106,7 +106,7 @@ extension Variable { /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable. - /// - equals: An integer literal value. + /// - value: An integer literal value. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, @@ -129,7 +129,7 @@ extension Variable { /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable. - /// - equals: A boolean literal value. + /// - value: A boolean literal value. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, @@ -152,7 +152,7 @@ extension Variable { /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable. - /// - equals: A double literal value. + /// - value: A double literal value. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, @@ -175,7 +175,7 @@ extension Variable { /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. /// - name: The name of the variable. /// - type: The type of the variable (TypeRepresentable). - /// - equals: The initial value expression of the variable, if any. + /// - defaultValue: The initial value expression of the variable, if any. /// - explicitType: Whether the variable has an explicit type. public init( _ kind: VariableKind, diff --git a/Sources/SyntaxKit/Variables/VariableDecl.swift b/Sources/SyntaxKit/Variables/VariableDecl.swift deleted file mode 100644 index 3460622..0000000 --- a/Sources/SyntaxKit/Variables/VariableDecl.swift +++ /dev/null @@ -1,97 +0,0 @@ -// -// VariableDecl.swift -// SyntaxKit -// -// Created by Leo Dion. -// Copyright © 2025 BrightDigit. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -import SwiftSyntax - -/// A Swift `let` or `var` declaration. -public struct VariableDecl: CodeBlock { - private let kind: VariableKind - private let name: String - private let value: String? - - /// Creates a `let` or `var` declaration. - /// - Parameters: - /// - kind: The kind of variable, either ``VariableKind/let`` or ``VariableKind/var``. - /// - name: The name of the variable. - /// - value: The initial value of the variable, if any. - public init(_ kind: VariableKind, name: String, equals value: String? = nil) { - self.kind = kind - self.name = name - self.value = value - } - - public var syntax: SyntaxProtocol { - let bindingKeyword = TokenSyntax.keyword(kind == .let ? .let : .var, trailingTrivia: .space) - let identifier = TokenSyntax.identifier(name, trailingTrivia: .space) - let initializer = value.map { value in - if value.hasPrefix("\"") && value.hasSuffix("\"") { - return InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment( - StringSegmentSyntax(content: .stringSegment(String(value.dropFirst().dropLast()))) - ) - ]), - closingQuote: .stringQuoteToken() - ) - ) - } else if value.contains("\\(") { - return InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: StringLiteralExprSyntax( - openingQuote: .stringQuoteToken(), - segments: StringLiteralSegmentListSyntax([ - .stringSegment( - StringSegmentSyntax(content: .stringSegment(value)) - ) - ]), - closingQuote: .stringQuoteToken() - ) - ) - } else { - return InitializerClauseSyntax( - equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), - value: ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(value))) - ) - } - } - return VariableDeclSyntax( - bindingSpecifier: bindingKeyword, - bindings: PatternBindingListSyntax([ - PatternBindingSyntax( - pattern: IdentifierPatternSyntax(identifier: identifier), - typeAnnotation: nil, - initializer: initializer - ) - ]) - ) - } -} diff --git a/Sources/SyntaxKit/Variables/VariableExp.swift b/Sources/SyntaxKit/Variables/VariableExp.swift index d8803b3..45d4b0f 100644 --- a/Sources/SyntaxKit/Variables/VariableExp.swift +++ b/Sources/SyntaxKit/Variables/VariableExp.swift @@ -41,14 +41,21 @@ public struct VariableExp: CodeBlock, PatternConvertible, ExprCodeBlock { /// Accesses a property on the variable. /// - Parameter propertyName: The name of the property to access. - /// - Returns: A ``PropertyAccessExp`` that represents the property access. - public func property(_ propertyName: String) -> PropertyAccessExp { + /// - Returns: A property accessible code block that represents the property access. + public func property(_ propertyName: String) -> PropertyAccessible { PropertyAccessExp(base: self, propertyName: propertyName) } + /// Negates property access on the variable. + /// - Parameter propertyName: The name of the property to access. + /// - Returns: A code block that represents the negated property access. + public func negatedProperty(_ propertyName: String) -> CodeBlock { + NegatedPropertyAccessExp(base: PropertyAccessExp(base: self, propertyName: propertyName)) + } + /// Calls a method on the variable. /// - Parameter methodName: The name of the method to call. - /// - Returns: A ``FunctionCallExp`` that represents the method call. + /// - Returns: A code block that represents the method call. public func call(_ methodName: String) -> CodeBlock { FunctionCallExp(baseName: name, methodName: methodName) } @@ -56,19 +63,18 @@ public struct VariableExp: CodeBlock, PatternConvertible, ExprCodeBlock { /// Calls a method on the variable with parameters. /// - Parameters: /// - methodName: The name of the method to call. - /// - params: A ``ParameterExpBuilder`` that provides the parameters for the method call. - /// - Returns: A ``FunctionCallExp`` that represents the method call. + /// - params: A ``ParameterExpBuilderResult`` that provides the parameters for the method call. + /// - Returns: A code block that represents the method call. public func call(_ methodName: String, @ParameterExpBuilderResult _ params: () -> [ParameterExp]) -> CodeBlock { FunctionCallExp(baseName: name, methodName: methodName, parameters: params()) } - /// Creates a reference to this variable. - /// - Parameter referenceType: The type of reference. - /// - Returns: A reference expression. - public func reference(_ referenceType: CaptureReferenceType) -> CodeBlock { - ReferenceExp(base: self, referenceType: referenceType) + /// Performs optional chaining on the variable. + /// - Returns: A code block that represents the optional chaining. + public func optionalChaining() -> CodeBlock { + OptionalChainingExp(base: self) } /// Creates an optional chaining expression for this variable. @@ -77,6 +83,13 @@ public struct VariableExp: CodeBlock, PatternConvertible, ExprCodeBlock { OptionalChainingExp(base: self) } + /// Creates a reference to the variable. + /// - Parameter referenceType: The type of reference to create. + /// - Returns: A code block that represents the reference. + public func reference(_ referenceType: CaptureReferenceType) -> CodeBlock { + ReferenceExp(base: self, referenceType: referenceType) + } + public var syntax: SyntaxProtocol { ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(name))) } diff --git a/Sources/SyntaxKit/Variables/VariableKind.swift b/Sources/SyntaxKit/Variables/VariableKind.swift index a81a0f6..1072af5 100644 --- a/Sources/SyntaxKit/Variables/VariableKind.swift +++ b/Sources/SyntaxKit/Variables/VariableKind.swift @@ -29,8 +29,8 @@ import Foundation -/// The kind of a variable declaration. -public enum VariableKind { +/// Represents the kind of variable declaration. +public enum VariableKind: Sendable, Equatable { /// A `let` declaration. case `let` /// A `var` declaration. diff --git a/Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift b/Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift index b44ed10..7cf55ec 100644 --- a/Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift +++ b/Tests/SyntaxKitTests/Integration/BlackjackCardTests.swift @@ -1,7 +1,6 @@ +import SyntaxKit import Testing -@testable import SyntaxKit - @Suite internal struct BlackjackCardTests { @Test internal func testBlackjackCardExample() throws { diff --git a/Tests/SyntaxKitTests/Integration/BlackjackTests.swift b/Tests/SyntaxKitTests/Integration/BlackjackTests.swift index 740f218..46ca6f7 100644 --- a/Tests/SyntaxKitTests/Integration/BlackjackTests.swift +++ b/Tests/SyntaxKitTests/Integration/BlackjackTests.swift @@ -1,7 +1,6 @@ +import SyntaxKit import Testing -@testable import SyntaxKit - internal struct BlackjackTests { @Test internal func testBlackjackCardExample() throws { let syntax = Struct("BlackjackCard") { @@ -131,7 +130,7 @@ internal struct BlackjackTests { Variable(.let, name: "rank", type: "Rank") Variable(.let, name: "suit", type: "Suit") ComputedProperty("description", type: "String") { - VariableDecl(.var, name: "output", equals: "suit is \\(suit.rawValue),") + Variable(.var, name: "output", equals: Literal.string("suit is \\(suit.rawValue),")) PlusAssign("output", " value is \\(rank.values.first)") If( Let("second", "rank.values.second"), diff --git a/Tests/SyntaxKitTests/Integration/CommentTests.swift b/Tests/SyntaxKitTests/Integration/CommentTests.swift index 6397f11..8557a19 100644 --- a/Tests/SyntaxKitTests/Integration/CommentTests.swift +++ b/Tests/SyntaxKitTests/Integration/CommentTests.swift @@ -1,7 +1,6 @@ +import SyntaxKit import Testing -@testable import SyntaxKit - internal struct CommentTests { @Test internal func testCommentInjection() { let syntax = Group { diff --git a/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift b/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift index a28ff50..986e834 100644 --- a/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/CompleteProtocolsExampleTests.swift @@ -105,11 +105,24 @@ import Testing .inherits("Vehicle", "Electric") // MARK: - Usage Example - VariableDecl(.let, name: "tesla", equals: "ElectricCar(brand: \"Tesla\", batteryLevel: 75.0)") - .comment { - Line("MARK: - Usage Example") + Variable( + .let, + name: "tesla", + equals: Init("ElectricCar") { + ParameterExp(name: "brand", value: Literal.string("Tesla")) + ParameterExp(name: "batteryLevel", value: Literal.float(75.0)) } - VariableDecl(.let, name: "toyota", equals: "Car(brand: \"Toyota\")") + ) + .comment { + Line("MARK: - Usage Example") + } + Variable( + .let, + name: "toyota", + equals: Init("Car") { + ParameterExp(name: "brand", value: Literal.string("Toyota")) + } + ) // Demonstrate protocol usage Function("demonstrateVehicle") { diff --git a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift index b312c83..b9c83e8 100644 --- a/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConcurrencyExampleTests.swift @@ -1,8 +1,7 @@ import Foundation +import SyntaxKit import Testing -@testable import SyntaxKit - @Suite internal struct ConcurrencyExampleTests { @Test("Concurrency vending machine DSL generates expected Swift code") internal func testConcurrencyVendingMachineExample() throws { diff --git a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift index 47d0821..c418e69 100644 --- a/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ConditionalsExampleTests.swift @@ -1,8 +1,7 @@ import Foundation +import SyntaxKit import Testing -@testable import SyntaxKit - @Suite internal struct ConditionalsExampleTests { @Test("Completed conditionals DSL generates expected Swift code") internal func testCompletedConditionalsExample() throws { diff --git a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift index c510e0d..740f013 100644 --- a/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/ForLoopsExampleTests.swift @@ -1,8 +1,7 @@ import Foundation +import SyntaxKit import Testing -@testable import SyntaxKit - @Suite internal struct ForLoopsExampleTests { @Test("Completed for loops DSL generates expected Swift code") internal func testCompletedForLoopsExample() throws { diff --git a/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift b/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift index 05806bd..d0529ef 100644 --- a/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift +++ b/Tests/SyntaxKitTests/Integration/SwiftUIExampleTests.swift @@ -28,10 +28,9 @@ // import Foundation +import SyntaxKit import Testing -@testable import SyntaxKit - @Suite internal struct SwiftUIExampleTests { @Test("SwiftUI example DSL generates expected Swift code") internal func testSwiftUIExample() throws { diff --git a/Tests/SyntaxKitTests/Unit/Expressions/LiteralValueTests.swift b/Tests/SyntaxKitTests/Unit/Expressions/LiteralValueTests.swift index f28ab60..aa50a12 100644 --- a/Tests/SyntaxKitTests/Unit/Expressions/LiteralValueTests.swift +++ b/Tests/SyntaxKitTests/Unit/Expressions/LiteralValueTests.swift @@ -112,50 +112,50 @@ internal struct LiteralValueTests { // MARK: - TupleLiteral Tests @Test internal func testTupleLiteralTypeName() { - let tuple1 = TupleLiteral([.int(1), .int(2)]) + let tuple1 = TupleLiteralArray([.int(1), .int(2)]) #expect(tuple1.typeName == "(Int, Int)") - let tuple2 = TupleLiteral([.string("hello"), .int(42), .boolean(true)]) + let tuple2 = TupleLiteralArray([.string("hello"), .int(42), .boolean(true)]) #expect(tuple2.typeName == "(String, Int, Bool)") - let tuple3 = TupleLiteral([.int(1), nil, .string("test")]) + let tuple3 = TupleLiteralArray([.int(1), nil, .string("test")]) #expect(tuple3.typeName == "(Int, Any, String)") - let tuple4 = TupleLiteral([nil, nil]) + let tuple4 = TupleLiteralArray([nil, nil]) #expect(tuple4.typeName == "(Any, Any)") } @Test internal func testTupleLiteralString() { - let tuple1 = TupleLiteral([.int(1), .int(2)]) + let tuple1 = TupleLiteralArray([.int(1), .int(2)]) #expect(tuple1.literalString == "(1, 2)") - let tuple2 = TupleLiteral([.string("hello"), .int(42), .boolean(true)]) + let tuple2 = TupleLiteralArray([.string("hello"), .int(42), .boolean(true)]) #expect(tuple2.literalString == "(\"hello\", 42, true)") - let tuple3 = TupleLiteral([.int(1), nil, .string("test")]) + let tuple3 = TupleLiteralArray([.int(1), nil, .string("test")]) #expect(tuple3.literalString == "(1, _, \"test\")") - let tuple4 = TupleLiteral([nil, nil]) + let tuple4 = TupleLiteralArray([nil, nil]) #expect(tuple4.literalString == "(_, _)") - let tuple5 = TupleLiteral([.float(3.14), .nil]) + let tuple5 = TupleLiteralArray([.float(3.14), .nil]) #expect(tuple5.literalString == "(3.14, nil)") } @Test internal func testTupleLiteralWithNestedTuples() { - let nestedTuple = TupleLiteral([.int(1), .tuple([.string("nested"), .int(2)])]) + let nestedTuple = TupleLiteralArray([.int(1), .tuple([.string("nested"), .int(2)])]) #expect(nestedTuple.typeName == "(Int, Any)") #expect(nestedTuple.literalString == "(1, (\"nested\", 2))") } @Test internal func testTupleLiteralWithRef() { - let tuple = TupleLiteral([.ref("variable"), .int(42)]) + let tuple = TupleLiteralArray([.ref("variable"), .int(42)]) #expect(tuple.typeName == "(Any, Int)") #expect(tuple.literalString == "(variable, 42)") } @Test internal func testEmptyTupleLiteral() { - let tuple = TupleLiteral([]) + let tuple = TupleLiteralArray([]) #expect(tuple.typeName == "()") #expect(tuple.literalString == "()") } @@ -163,7 +163,7 @@ internal struct LiteralValueTests { // MARK: - TupleLiteral Code Generation Tests @Test internal func testVariableWithTupleLiteral() { - let tuple = TupleLiteral([.int(1), .int(2)]) + let tuple = TupleLiteralArray([.int(1), .int(2)]) let variable = Variable(.let, name: "point", equals: tuple) let generated = variable.syntax.description @@ -172,7 +172,7 @@ internal struct LiteralValueTests { } @Test internal func testVariableWithTupleLiteralWithExplicitType() { - let tuple = TupleLiteral([.int(1), .int(2)]) + let tuple = TupleLiteralArray([.int(1), .int(2)]) let variable = Variable(.let, name: "point", equals: tuple).withExplicitType() let generated = variable.syntax.description @@ -181,7 +181,7 @@ internal struct LiteralValueTests { } @Test internal func testVariableWithComplexTupleLiteral() { - let tuple = TupleLiteral([.string("hello"), .int(42), .boolean(true)]) + let tuple = TupleLiteralArray([.string("hello"), .int(42), .boolean(true)]) let variable = Variable(.let, name: "data", equals: tuple).withExplicitType() let generated = variable.syntax.description @@ -190,7 +190,7 @@ internal struct LiteralValueTests { } @Test internal func testVariableWithTupleLiteralWithWildcards() { - let tuple = TupleLiteral([.int(1), nil, .string("test")]) + let tuple = TupleLiteralArray([.int(1), nil, .string("test")]) let variable = Variable(.let, name: "partial", equals: tuple).withExplicitType() let generated = variable.syntax.description diff --git a/Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift b/Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift index c92a763..56b9cd6 100644 --- a/Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift +++ b/Tests/SyntaxKitTests/Unit/Migration/CodeStyleMigrationTests.swift @@ -29,7 +29,7 @@ internal struct CodeStyleMigrationTests { Function("method") { Parameter(name: "param", type: "String") } _: { - VariableDecl(.let, name: "local", equals: "\"value\"") + Variable(.let, name: "local", equals: .string("value")) Return { VariableExp("local") }