@@ -31,6 +31,23 @@ private let BASE_KIND_FILES = [
31
31
" Type " : " SyntaxTypeNodes.swift " ,
32
32
]
33
33
34
+ struct GeneratedFileSpec {
35
+ let pathComponents : [ String ]
36
+ private let contentsGenerator : ( ) -> String
37
+ var contents : String {
38
+ return self . contentsGenerator ( )
39
+ }
40
+
41
+ init ( _ pathComponents: [ String ] , _ contents: @escaping @autoclosure ( ) -> String ) {
42
+ self . pathComponents = pathComponents
43
+ self . contentsGenerator = contents
44
+ }
45
+
46
+ init ( _ pathComponents: [ String ] , _ contents: @escaping @autoclosure ( ) -> SourceFileSyntax ) {
47
+ self . init ( pathComponents, " \( contents ( ) . formatted ( using: CodeGenerationFormat ( ) ) ) \n " )
48
+ }
49
+ }
50
+
34
51
struct TemplateSpec {
35
52
let sourceFileGenerator : ( ) -> SourceFileSyntax
36
53
var sourceFile : SourceFileSyntax {
@@ -55,49 +72,51 @@ struct GenerateSwiftSyntax: ParsableCommand {
55
72
var verbose : Bool = false
56
73
57
74
func run( ) throws {
58
- let templates : [ TemplateSpec ] =
75
+ let fileSpecs : [ GeneratedFileSpec ] =
59
76
[
60
77
// SwiftBasicFormat
61
- TemplateSpec ( sourceFile : basicFormatFile , module : swiftBasicFormatDir , filename : " BasicFormat.swift " ) ,
78
+ GeneratedFileSpec ( [ swiftBasicFormatDir , " generated " , " BasicFormat.swift " ] , basicFormatFile ) ,
62
79
63
80
// IDEUtils
64
- TemplateSpec ( sourceFile : syntaxClassificationFile , module : ideUtilsDir , filename : " SyntaxClassification.swift " ) ,
81
+ GeneratedFileSpec ( [ ideUtilsDir , " generated " , " SyntaxClassification.swift " ] , syntaxClassificationFile ) ,
65
82
66
83
// SwiftParser
67
- TemplateSpec ( sourceFile : declarationModifierFile , module : swiftParserDir , filename : " DeclarationModifier.swift " ) ,
68
- TemplateSpec ( sourceFile : parserEntryFile , module : swiftParserDir , filename : " Parser+Entry.swift " ) ,
69
- TemplateSpec ( sourceFile : tokenSpecStaticMembersFile , module : swiftParserDir , filename : " TokenSpecStaticMembers.swift " ) ,
70
- TemplateSpec ( sourceFile : typeAttributeFile , module : swiftParserDir , filename : " TypeAttribute.swift " ) ,
84
+ GeneratedFileSpec ( [ swiftParserDir , " generated " , " DeclarationModifier.swift " ] , declarationModifierFile ) ,
85
+ GeneratedFileSpec ( [ swiftParserDir , " generated " , " Parser+Entry.swift " ] , parserEntryFile ) ,
86
+ GeneratedFileSpec ( [ swiftParserDir , " generated " , " TokenSpecStaticMembers.swift " ] , tokenSpecStaticMembersFile ) ,
87
+ GeneratedFileSpec ( [ swiftParserDir , " generated " , " TypeAttribute.swift " ] , typeAttributeFile ) ,
71
88
72
89
// SwiftSyntax
73
- TemplateSpec ( sourceFile : keywordFile , module : swiftSyntaxDir , filename : " Keyword.swift " ) ,
74
- TemplateSpec ( sourceFile : miscFile , module : swiftSyntaxDir , filename : " Misc.swift " ) ,
75
- TemplateSpec ( sourceFile : rawSyntaxNodesFile , module : swiftSyntaxDir , filename : " raw/ RawSyntaxNodes.swift " ) ,
76
- TemplateSpec ( sourceFile : rawSyntaxValidationFile , module : swiftSyntaxDir , filename : " raw/ RawSyntaxValidation.swift " ) ,
77
- TemplateSpec ( sourceFile : syntaxAnyVisitorFile , module : swiftSyntaxDir , filename : " SyntaxAnyVisitor.swift " ) ,
78
- TemplateSpec ( sourceFile : syntaxBaseNodesFile , module : swiftSyntaxDir , filename : " SyntaxBaseNodes.swift " ) ,
79
- TemplateSpec ( sourceFile : syntaxCollectionsFile , module : swiftSyntaxDir , filename : " SyntaxCollections.swift " ) ,
80
- TemplateSpec ( sourceFile : syntaxEnumFile , module : swiftSyntaxDir , filename : " SyntaxEnum.swift " ) ,
81
- TemplateSpec ( sourceFile : syntaxKindFile , module : swiftSyntaxDir , filename : " SyntaxKind.swift " ) ,
82
- TemplateSpec ( sourceFile : syntaxRewriterFile , module : swiftSyntaxDir , filename : " SyntaxRewriter.swift " ) ,
83
- TemplateSpec ( sourceFile : syntaxTraitsFile , module : swiftSyntaxDir , filename : " SyntaxTraits.swift " ) ,
84
- TemplateSpec ( sourceFile : syntaxTransformFile , module : swiftSyntaxDir , filename : " SyntaxTransform.swift " ) ,
85
- TemplateSpec ( sourceFile : syntaxVisitorFile , module : swiftSyntaxDir , filename : " SyntaxVisitor.swift " ) ,
86
- TemplateSpec ( sourceFile : tokenKindFile , module : swiftSyntaxDir , filename : " TokenKind.swift " ) ,
87
- TemplateSpec ( sourceFile : tokensFile , module : swiftSyntaxDir , filename : " Tokens.swift " ) ,
88
- TemplateSpec ( sourceFile : triviaFile , module : swiftSyntaxDir , filename : " Trivia.swift " ) ,
90
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " Keyword.swift " ] , keywordFile ) ,
91
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " Misc.swift " ] , miscFile ) ,
92
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " raw " , " RawSyntaxNodes.swift " ] , rawSyntaxNodesFile ) ,
93
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " raw " , " RawSyntaxValidation.swift " ] , rawSyntaxValidationFile ) ,
94
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxAnyVisitor.swift " ] , syntaxAnyVisitorFile ) ,
95
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxBaseNodes.swift " ] , syntaxBaseNodesFile ) ,
96
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxCollections.swift " ] , syntaxCollectionsFile ) ,
97
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxEnum.swift " ] , syntaxEnumFile ) ,
98
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxKind.swift " ] , syntaxKindFile ) ,
99
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxRewriter.swift " ] , syntaxRewriterFile ) ,
100
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxTraits.swift " ] , syntaxTraitsFile ) ,
101
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxTransform.swift " ] , syntaxTransformFile ) ,
102
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " SyntaxVisitor.swift " ] , syntaxVisitorFile ) ,
103
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " TokenKind.swift " ] , tokenKindFile ) ,
104
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " Tokens.swift " ] , tokensFile ) ,
105
+ GeneratedFileSpec ( [ swiftSyntaxDir , " generated " , " Trivia.swift " ] , triviaFile ) ,
89
106
90
107
// SwiftSyntaxBuilder
91
- TemplateSpec ( sourceFile : buildableCollectionNodesFile , module : swiftSyntaxBuilderDir , filename : " BuildableCollectionNodes.swift " ) ,
92
- TemplateSpec ( sourceFile : buildableNodesFile , module : swiftSyntaxBuilderDir , filename : " BuildableNodes.swift " ) ,
93
- TemplateSpec ( sourceFile : resultBuildersFile , module : swiftSyntaxBuilderDir , filename : " ResultBuilders.swift " ) ,
94
- TemplateSpec ( sourceFile : syntaxExpressibleByStringInterpolationConformancesFile , module : swiftSyntaxBuilderDir , filename : " SyntaxExpressibleByStringInterpolationConformances.swift " ) ,
108
+ GeneratedFileSpec ( [ swiftSyntaxBuilderDir , " generated " , " BuildableCollectionNodes.swift " ] , buildableCollectionNodesFile ) ,
109
+ GeneratedFileSpec ( [ swiftSyntaxBuilderDir , " generated " , " BuildableNodes.swift " ] , buildableNodesFile ) ,
110
+ GeneratedFileSpec ( [ swiftSyntaxBuilderDir , " generated " , " ResultBuilders.swift " ] , resultBuildersFile ) ,
111
+ GeneratedFileSpec ( [ swiftSyntaxBuilderDir , " generated " , " SyntaxExpressibleByStringInterpolationConformances.swift " ] , syntaxExpressibleByStringInterpolationConformancesFile ) ,
95
112
]
96
113
+ BASE_KIND_FILES. map { baseKind in
97
- TemplateSpec ( sourceFile: syntaxNode ( emitKind: baseKind. key) , module: swiftSyntaxDir, filename: " syntaxNodes/ \( baseKind. value) " )
98
- }
114
+ GeneratedFileSpec ( [ swiftSyntaxDir, " generated " , " syntaxNodes " , baseKind. value] , syntaxNode ( emitKind: baseKind. key) )
115
+ } + [
116
+ GeneratedFileSpec ( [ swiftSyntaxDir, " Documentation.docc " , " generated " , " SwiftSyntax.md " ] , swiftSyntaxDoccIndex)
117
+ ]
99
118
100
- let modules = Set ( templates . map ( \ . module ) )
119
+ let modules = Set ( fileSpecs . compactMap { $0 . pathComponents . first } )
101
120
102
121
let previouslyGeneratedFilesLock = NSLock ( )
103
122
var previouslyGeneratedFiles = Set (
@@ -108,25 +127,25 @@ struct GenerateSwiftSyntax: ParsableCommand {
108
127
return FileManager . default
109
128
. enumerator ( at: generatedDir, includingPropertiesForKeys: nil ) !
110
129
. compactMap { $0 as? URL }
111
- . filter { $0. pathExtension == " swift " }
130
+ . filter { ! $0. hasDirectoryPath }
112
131
}
113
132
)
114
133
115
134
var errors : [ Error ] = [ ]
116
- DispatchQueue . concurrentPerform ( iterations: templates . count) { index in
117
- let template = templates [ index]
135
+ DispatchQueue . concurrentPerform ( iterations: fileSpecs . count) { index in
136
+ let fileSpec = fileSpecs [ index]
118
137
do {
119
- let destination = URL ( fileURLWithPath: destination)
120
- . appendingPathComponent ( template . module )
121
- . appendingPathComponent ( " generated " )
122
- . appendingPathComponent ( template . filename )
138
+ var destination = URL ( fileURLWithPath: destination)
139
+ for component in fileSpec . pathComponents {
140
+ destination = destination . appendingPathComponent ( component )
141
+ }
123
142
124
143
previouslyGeneratedFilesLock. lock ( ) ;
125
144
_ = previouslyGeneratedFiles. remove ( destination)
126
145
previouslyGeneratedFilesLock. unlock ( )
127
146
128
- try generateTemplate (
129
- sourceFile : template . sourceFile ,
147
+ try generateFile (
148
+ contents : fileSpec . contents ,
130
149
destination: destination,
131
150
verbose: verbose
132
151
)
@@ -147,8 +166,8 @@ struct GenerateSwiftSyntax: ParsableCommand {
147
166
}
148
167
}
149
168
150
- private func generateTemplate (
151
- sourceFile : SourceFileSyntax ,
169
+ private func generateFile (
170
+ contents : @autoclosure ( ) -> String ,
152
171
destination: URL ,
153
172
verbose: Bool
154
173
) throws {
@@ -161,7 +180,10 @@ struct GenerateSwiftSyntax: ParsableCommand {
161
180
if verbose {
162
181
print ( " Generating \( destination. path) ... " )
163
182
}
164
- let syntax = sourceFile. formatted ( using: CodeGenerationFormat ( ) )
165
- try " \( syntax) \n " . write ( to: destination, atomically: true , encoding: . utf8)
183
+ let start = Date ( )
184
+ try contents ( ) . write ( to: destination, atomically: true , encoding: . utf8)
185
+ if verbose {
186
+ print ( " Generated \( destination. path) in \( ( Date ( ) . timeIntervalSince ( start) * 1000 ) . rounded ( ) / 1000 ) s " )
187
+ }
166
188
}
167
189
}
0 commit comments