Skip to content

[CodeGeneration] Generate all files in '/generatedSources' directory #2969

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
wants to merge 1 commit into from
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,6 @@ import SwiftSyntaxBuilder
import SyntaxSupport
import Utils

private let generatedDirName = "generated"

private let swiftBasicFormatGeneratedDir = ["SwiftBasicFormat", generatedDirName]
private let swiftideUtilsGeneratedDir = ["SwiftIDEUtils", generatedDirName]
private let swiftParserGeneratedDir = ["SwiftParser", generatedDirName]
private let swiftParserDiagnosticsGeneratedDir = ["SwiftParserDiagnostics", generatedDirName]
private let swiftSyntaxGeneratedDir = ["SwiftSyntax", generatedDirName]
private let swiftSyntaxBuilderGeneratedDir = ["SwiftSyntaxBuilder", generatedDirName]
private let BASE_KIND_FILES: [SyntaxNodeKind: String] = [
.decl: "SyntaxDeclNodes.swift",
.expr: "SyntaxExprNodes.swift",
.pattern: "SyntaxPatternNodes.swift",
.stmt: "SyntaxStmtNodes.swift",
.syntax: "SyntaxNodes.swift",
.type: "SyntaxTypeNodes.swift",
]

struct GeneratedFileSpec {
let pathComponents: [String]
private let contentsGenerator: () -> String
Expand Down Expand Up @@ -74,15 +57,16 @@ struct TemplateSpec {
@main
struct GenerateSwiftSyntax: AsyncParsableCommand {
@Argument(
help: "The path to the source directory (i.e. 'swift-syntax/Sources') where the source files are to be generated"
help:
"The path to the generated source directory (i.e. 'swift-syntax/generatedSources') where the files are to be generated"
)
var destination: String = {
let sourcesURL = URL(fileURLWithPath: #filePath)
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
.appendingPathComponent("Sources")
.appendingPathComponent("generatedSources")
return sourcesURL.path
}()

Expand All @@ -94,61 +78,52 @@ struct GenerateSwiftSyntax: AsyncParsableCommand {

var fileSpecs: [GeneratedFileSpec] = [
// SwiftParser
GeneratedFileSpec(swiftParserGeneratedDir + ["ExperimentalFeatures.swift"], experimentalFeaturesFile),
GeneratedFileSpec(swiftParserGeneratedDir + ["IsLexerClassified.swift"], isLexerClassifiedFile),
GeneratedFileSpec(swiftParserGeneratedDir + ["LayoutNodes+Parsable.swift"], layoutNodesParsableFile),
GeneratedFileSpec(swiftParserGeneratedDir + ["Parser+TokenSpecSet.swift"], parserTokenSpecSetFile),
GeneratedFileSpec(swiftParserGeneratedDir + ["TokenSpecStaticMembers.swift"], tokenSpecStaticMembersFile),
GeneratedFileSpec(["SwiftParser", "ExperimentalFeatures.swift"], experimentalFeaturesFile),
GeneratedFileSpec(["SwiftParser", "IsLexerClassified.swift"], isLexerClassifiedFile),
GeneratedFileSpec(["SwiftParser", "LayoutNodes+Parsable.swift"], layoutNodesParsableFile),
GeneratedFileSpec(["SwiftParser", "Parser+TokenSpecSet.swift"], parserTokenSpecSetFile),
GeneratedFileSpec(["SwiftParser", "TokenSpecStaticMembers.swift"], tokenSpecStaticMembersFile),

// SwiftParserDiagnostics
GeneratedFileSpec(["SwiftParserDiagnostics", "ChildNameForDiagnostics.swift"], childNameForDiagnosticFile),
GeneratedFileSpec(
swiftParserDiagnosticsGeneratedDir + ["ChildNameForDiagnostics.swift"],
childNameForDiagnosticFile
),
GeneratedFileSpec(
swiftParserDiagnosticsGeneratedDir + ["SyntaxKindNameForDiagnostics.swift"],
["SwiftParserDiagnostics", "SyntaxKindNameForDiagnostics.swift"],
syntaxKindNameForDiagnosticFile
),
GeneratedFileSpec(
swiftParserDiagnosticsGeneratedDir + ["TokenNameForDiagnostics.swift"],
tokenNameForDiagnosticFile
),
GeneratedFileSpec(["SwiftParserDiagnostics", "TokenNameForDiagnostics.swift"], tokenNameForDiagnosticFile),

// SwiftSyntax
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["ChildNameForKeyPath.swift"], childNameForKeyPathFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["Keyword.swift"], keywordFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["raw", "RawSyntaxValidation.swift"], rawSyntaxValidationFile),
GeneratedFileSpec(["SwiftSyntax", "ChildNameForKeyPath.swift"], childNameForKeyPathFile),
GeneratedFileSpec(["SwiftSyntax", "Keyword.swift"], keywordFile),
GeneratedFileSpec(["SwiftSyntax", "raw", "RawSyntaxValidation.swift"], rawSyntaxValidationFile),
GeneratedFileSpec(["SwiftSyntax", "RenamedChildrenCompatibility.swift"], renamedChildrenCompatibilityFile),
GeneratedFileSpec(["SwiftSyntax", "RenamedNodesCompatibility.swift"], renamedSyntaxNodesFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxAnyVisitor.swift"], syntaxAnyVisitorFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxBaseNodes.swift"], syntaxBaseNodesFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxCollections.swift"], syntaxCollectionsFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxEnum.swift"], syntaxEnumFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxKind.swift"], syntaxKindFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxRewriter.swift"], syntaxRewriterFile),
GeneratedFileSpec(["SwiftSyntax", "SyntaxTraits.swift"], syntaxTraitsFile),
GeneratedFileSpec(
swiftSyntaxGeneratedDir + ["RenamedChildrenCompatibility.swift"],
renamedChildrenCompatibilityFile
),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["RenamedNodesCompatibility.swift"], renamedSyntaxNodesFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxAnyVisitor.swift"], syntaxAnyVisitorFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxBaseNodes.swift"], syntaxBaseNodesFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxCollections.swift"], syntaxCollectionsFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxEnum.swift"], syntaxEnumFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxKind.swift"], syntaxKindFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxRewriter.swift"], syntaxRewriterFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxTraits.swift"], syntaxTraitsFile),
GeneratedFileSpec(
swiftSyntaxGeneratedDir + ["SyntaxVisitor.swift"],
["SwiftSyntax", "SyntaxVisitor.swift"],
syntaxVisitorFile,
format: CodeGenerationFormat(maxElementsOnSameLine: 4)
),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["TokenKind.swift"], tokenKindFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["Tokens.swift"], tokensFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["TriviaPieces.swift"], triviaPiecesFile),
GeneratedFileSpec(["SwiftSyntax", "Documentation.docc", "generated", "SwiftSyntax.md"], swiftSyntaxDoccIndex),
GeneratedFileSpec(["SwiftSyntax", "TokenKind.swift"], tokenKindFile),
GeneratedFileSpec(["SwiftSyntax", "Tokens.swift"], tokensFile),
GeneratedFileSpec(["SwiftSyntax", "TriviaPieces.swift"], triviaPiecesFile),
GeneratedFileSpec(["SwiftSyntax", "Documentation.docc", "SwiftSyntax.md"], swiftSyntaxDoccIndex),

// SwiftSyntaxBuilder
GeneratedFileSpec(swiftSyntaxBuilderGeneratedDir + ["BuildableNodes.swift"], buildableNodesFile),
GeneratedFileSpec(swiftSyntaxBuilderGeneratedDir + ["ResultBuilders.swift"], resultBuildersFile),
GeneratedFileSpec(["SwiftSyntaxBuilder", "BuildableNodes.swift"], buildableNodesFile),
GeneratedFileSpec(["SwiftSyntaxBuilder", "ResultBuilders.swift"], resultBuildersFile),
GeneratedFileSpec(
swiftSyntaxBuilderGeneratedDir + ["SyntaxExpressibleByStringInterpolationConformances.swift"],
["SwiftSyntaxBuilder", "SyntaxExpressibleByStringInterpolationConformances.swift"],
syntaxExpressibleByStringInterpolationConformancesFile
),
GeneratedFileSpec(
swiftSyntaxBuilderGeneratedDir + ["RenamedChildrenBuilderCompatibility.swift"],
["SwiftSyntaxBuilder", "RenamedChildrenBuilderCompatibility.swift"],
renamedChildrenBuilderCompatibilityFile
),
]
Expand All @@ -158,30 +133,22 @@ struct GenerateSwiftSyntax: AsyncParsableCommand {
(letters: String) -> [GeneratedFileSpec] in
[
GeneratedFileSpec(
swiftSyntaxGeneratedDir + ["syntaxNodes", "SyntaxNodes\(letters).swift"],
["SwiftSyntax", "syntaxNodes", "SyntaxNodes\(letters).swift"],
syntaxNode(nodesStartingWith: Array(letters))
),
GeneratedFileSpec(
swiftSyntaxGeneratedDir + ["raw", "RawSyntaxNodes\(letters).swift"],
["SwiftSyntax", "raw", "RawSyntaxNodes\(letters).swift"],
rawSyntaxNodesFile(nodesStartingWith: Array(letters))
),
]
}

let modules = Set(fileSpecs.compactMap { $0.pathComponents.first })

var previouslyGeneratedFiles = Set(
modules.flatMap { (module) -> [URL] in
let generatedDir =
destination
.appendingPathComponent(module)
.appendingPathComponent("generated")
return FileManager.default
.enumerator(at: generatedDir, includingPropertiesForKeys: nil)!
.compactMap { $0 as? URL }
.filter { !$0.hasDirectoryPath }
.map { $0.resolvingSymlinksInPath() }
}
FileManager.default
.enumerator(at: destination, includingPropertiesForKeys: nil)!
.compactMap { $0 as? URL }
.filter { !$0.hasDirectoryPath }
.map { $0.resolvingSymlinksInPath() }
)

await withTaskGroup(of: (url: URL, error: Error?).self) { group in
Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftParser/generated
1 change: 1 addition & 0 deletions Sources/SwiftParserDiagnostics/generated
1 change: 1 addition & 0 deletions Sources/SwiftSyntax/Documentation.docc/generated
1 change: 1 addition & 0 deletions Sources/SwiftSyntax/generated
1 change: 1 addition & 0 deletions Sources/SwiftSyntaxBuilder/generated
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Foundation
/// Directories that should not be formatted.
fileprivate let directoriesToExclude = [
"lit_tests",
"generated",
"generatedSources",
"build",
"Inputs",
".build",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct GenerateSourceCode: ParsableCommand {
toolchain: try arguments.toolchain,
verbose: arguments.verbose
)
try executor.run(sourceDir: Paths.sourcesDir)
try executor.run(destinationDir: Paths.generatedSourcesDir)
}
}

Expand All @@ -46,13 +46,13 @@ struct GenerateSourceCodeExecutor {
self.verbose = verbose
}

func run(sourceDir: URL) throws {
func run(destinationDir: URL) throws {
logSection("Running code generation")

var args = [
"run",
"--package-path", Paths.codeGenerationDir.relativePath,
"generate-swift-syntax", sourceDir.relativePath,
"generate-swift-syntax", destinationDir.relativePath,
]

if verbose {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct LocalPrPrecheckExecutor {

func run() throws {
try formatExecutor.run()
try generateSourceCodeExecutor.run(sourceDir: Paths.sourcesDir)
try generateSourceCodeExecutor.run(destinationDir: Paths.generatedSourcesDir)
try buildExecutor.run()
try testExecutor.run()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ import ArgumentParser
import Foundation
import RegexBuilder

fileprivate let modules: [String] = [
"SwiftParser",
"SwiftParserDiagnostics",
"SwiftSyntax",
"SwiftSyntaxBuilder",
]

struct VerifySourceCode: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Verify that the generated sources match the ones checked into the repository."
Expand Down Expand Up @@ -66,40 +59,37 @@ struct VerifySourceCodeExecutor {
}

private func verifyCodeGeneratedFiles(tempDir: URL) throws {
try generateSourceCodeExecutor.run(sourceDir: tempDir)
try generateSourceCodeExecutor.run(destinationDir: tempDir)

logSection("Verifing code generated files")

for module in modules {
let selfGeneratedDir = tempDir.appendingPathComponent(module).appendingPathComponent("generated")
let userGeneratedDir = Paths.sourcesDir.appendingPathComponent(module).appendingPathComponent("generated")

let process = ProcessRunner(
executableURL: try Paths.diffExec,
arguments: [
"--recursive",
"--exclude",
".*", // Exclude dot files like .DS_Store
"--context=0",
selfGeneratedDir.path,
userGeneratedDir.path,
]
)
let selfGeneratedDir = tempDir
let userGeneratedDir = Paths.generatedSourcesDir

let process = ProcessRunner(
executableURL: try Paths.diffExec,
arguments: [
"--recursive",
"--exclude",
".*", // Exclude dot files like .DS_Store
"--context=0",
selfGeneratedDir.path,
userGeneratedDir.path,
]
)

let result = try process.run(verbose: verbose)

let result = try process.run(verbose: verbose)

if !result.stderr.isEmpty {
throw ScriptExectutionError(
message: """
FAIL: code-generated files committed to repository do
not match generated ones. Please re-generate the
code-generated-files using the following command, open a PR to the
SwiftSyntax project and merge it alongside the main PR.
$ swift run swift-syntax-dev-utils generate-source-code
/path/to/toolchain.xctoolchain/usr
"""
)
}
if !result.stderr.isEmpty {
throw ScriptExectutionError(
message: """
FAIL: code-generated files committed to repository do
not match generated ones. Please re-generate the
code-generated-files using the following command, open a PR to the
SwiftSyntax project and merge it alongside the main PR.
$ swift run swift-syntax-dev-utils generate-source-code
"""
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ enum Paths {
.appendingPathComponent("Sources")
}

static var generatedSourcesDir: URL {
packageDir
.appendingPathComponent("generatedSources")
}

static var examplesDir: URL {
packageDir
.appendingPathComponent("Examples")
Expand Down