Skip to content

Verify that files generated with SwiftSyntaxBuilder match the checked-in state #1117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions CodeGeneration/Package.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// swift-tools-version:5.7

import PackageDescription
import Foundation

let package = Package(
name: "CodeGeneration",
Expand All @@ -12,10 +13,6 @@ let package = Package(
.executable(name: "generate-swiftideutils", targets: ["generate-swiftideutils"]),
.executable(name: "generate-swiftsyntaxbuilder", targets: ["generate-swiftsyntaxbuilder"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", revision: "cdbdcbabb78d14e5e8d4915a115e3d843868ab8d"),
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.1.4")),
],
targets: [
.executableTarget(
name: "generate-swiftbasicformat",
Expand Down Expand Up @@ -78,3 +75,19 @@ let package = Package(
),
]
)

if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
// Building standalone.
package.dependencies += [
.package(url: "https://github.com/apple/swift-syntax.git", revision: "cdbdcbabb78d14e5e8d4915a115e3d843868ab8d"),
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.1.4")),
]
} else {
guard let swiftSyntaxPath = ProcessInfo.processInfo.environment["SWIFTCI_SWIFTSYNTAX_PATH"] else {
fatalError("If SWIFTCI_USE_LOCAL_DEPS is specified, SWIFTCI_SWIFTSYNTAX_PATH must point to a checkout of SwiftSyntax of the same commit that's mentioned in the standalone build")
}
package.dependencies += [
.package(name: "swift-syntax", path: swiftSyntaxPath),
.package(path: "../../swift-argument-parser"),
]
}
60 changes: 47 additions & 13 deletions build-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import argparse
import os
import platform
import re
import subprocess
import sys
import tempfile
Expand Down Expand Up @@ -341,10 +342,15 @@ def generate_gyb_files(
print("** Done Generating gyb Files **")


# If swiftsyntax_checkout is specified, a SwiftSyntax checkout with the commit that's
# used for CodeGeneration is assumed at that location, otherwise SwiftSyntax will be
# pulled at the correct commit from the internet. This is useful to verify files
# generated using CodeGeneration in CI that doesn't have internet access.
def run_code_generation(
swiftideutils_destination: str,
swiftbasicformat_destination: str,
swiftsyntaxbuilder_destination: str,
local_swiftsyntax_checkout: Optional[str],
toolchain: str,
verbose: bool
) -> None:
Expand All @@ -370,6 +376,9 @@ def run_code_generation(

env = dict(os.environ)
env["SWIFT_BUILD_SCRIPT_ENVIRONMENT"] = "1"
if local_swiftsyntax_checkout:
env["SWIFTCI_USE_LOCAL_DEPS"] = "1"
env["SWIFTCI_SWIFTSYNTAX_PATH"] = local_swiftsyntax_checkout
check_call(swiftpm_call, env=env, verbose=verbose)


Expand Down Expand Up @@ -505,6 +514,20 @@ def verify_gyb_generated_files(gyb_exec: str, verbose: bool) -> None:
)


# Parses the package manifest of CodeGeneration to find the SwiftSyntax commit it
# references.
def get_swiftsyntax_commit_for_codegeneration() -> str:
with open(os.path.join(CODE_GENERATION_DIR, 'Package.swift')) as \
codegen_package_manifest:
for line in codegen_package_manifest:
match = re.search(r'.package\(url: "https://github.com/apple/swift-syntax.git", revision: "([0-9a-f]+)"\)', line) # noqa: E501
if match:
return match.group(1)

fatal_error('Could not find commit of SwiftSyntax that CodeGeneration references')
return '' # Make Python's type checker happy


def verify_code_generated_files(
toolchain: str, verbose: bool
) -> None:
Expand All @@ -522,19 +545,29 @@ def verify_code_generated_files(
self_swiftbasicformat_generated_dir = tempfile.mkdtemp()
self_swiftsyntaxbuilder_generated_dir = tempfile.mkdtemp()

try:
run_code_generation(
swiftideutils_destination=self_swiftideutils_generated_dir,
swiftbasicformat_destination=self_swiftsyntaxbuilder_generated_dir,
swiftsyntaxbuilder_destination=self_swiftsyntaxbuilder_generated_dir,
toolchain=toolchain,
verbose=verbose
)
except subprocess.CalledProcessError as e:
fail_for_called_process_error(
"Source generation using SwiftSyntaxBuilder failed",
e
)
with tempfile.TemporaryDirectory(dir=os.path.dirname(PACKAGE_DIR)) as \
local_swiftsyntax_checkout:
# Perform a local clone of SwiftSyntax that we can check out at the commit that
# CodeGeneration expects.
check_call(['git', 'clone', PACKAGE_DIR, local_swiftsyntax_checkout],
verbose=verbose)
check_call(['git', 'checkout', get_swiftsyntax_commit_for_codegeneration()],
cwd=local_swiftsyntax_checkout, verbose=verbose)

try:
run_code_generation(
swiftideutils_destination=self_swiftideutils_generated_dir,
swiftbasicformat_destination=self_swiftbasicformat_generated_dir,
swiftsyntaxbuilder_destination=self_swiftsyntaxbuilder_generated_dir,
local_swiftsyntax_checkout=local_swiftsyntax_checkout,
toolchain=toolchain,
verbose=verbose
)
except subprocess.CalledProcessError as e:
fail_for_called_process_error(
"Source generation using SwiftSyntaxBuilder failed",
e
)

print("** Verifing code generated files **")

Expand Down Expand Up @@ -729,6 +762,7 @@ def generate_source_code_command(args: argparse.Namespace) -> None:
swiftideutils_destination=swiftideutils_destination,
swiftbasicformat_destination=swiftbasicformat_destination,
swiftsyntaxbuilder_destination=swiftsyntaxbuilder_destination,
local_swiftsyntax_checkout=None,
toolchain=args.toolchain,
verbose=args.verbose
)
Expand Down