@@ -15,6 +15,7 @@ import PackageModel
1515import SwiftParser
1616import SwiftSyntax
1717import SwiftSyntaxBuilder
18+ import struct TSCUtility. Version
1819
1920/// Add a target to a manifest's source code.
2021public struct AddTarget {
@@ -34,7 +35,8 @@ public struct AddTarget {
3435 /// new target.
3536 public static func addTarget(
3637 _ target: TargetDescription ,
37- to manifest: SourceFileSyntax
38+ to manifest: SourceFileSyntax ,
39+ installedSwiftPMConfiguration: InstalledSwiftPMConfiguration = . default
3840 ) throws -> PackageEditResult {
3941 // Make sure we have a suitable tools version in the manifest.
4042 try manifest. checkEditManifestToolsVersion ( )
@@ -53,7 +55,7 @@ public struct AddTarget {
5355 target. dependencies. append ( contentsOf: macroTargetDependencies)
5456 }
5557
56- let manifestEdits = try packageCall. appendingToArrayArgument (
58+ var newPackageCall = try packageCall. appendingToArrayArgument (
5759 label: " targets " ,
5860 trailingLabels: Self . argumentLabelsAfterTargets,
5961 newElement: target. asSyntax ( )
@@ -66,7 +68,11 @@ public struct AddTarget {
6668 }
6769
6870 guard let outerDirectory else {
69- return PackageEditResult ( manifestEdits: manifestEdits)
71+ return PackageEditResult (
72+ manifestEdits: [
73+ . replace( packageCall, with: newPackageCall. description)
74+ ]
75+ )
7076 }
7177
7278 let outerPath = try RelativePath ( validating: outerDirectory)
@@ -82,31 +88,49 @@ public struct AddTarget {
8288 )
8389
8490 // Perform any other actions that are needed for this target type.
91+ var extraManifestEdits : [ SourceEdit ] = [ ]
8592 switch target. type {
8693 case . macro:
87- // Macros need a file that introduces the main entrypoint
88- // describing all of the macros.
89- auxiliaryFiles. addSourceFile (
90- path: outerPath. appending (
91- components: [ target. name, " ProvidedMacros.swift " ]
92- ) ,
93- sourceCode: """
94- import SwiftCompilerPlugin
95-
96- @main
97- struct \( raw: target. name) Macros: CompilerPlugin {
98- let providingMacros: [Macro.Type] = [
99- \( raw: target. name) .self,
100- ]
101- }
102- """
94+ addProvidedMacrosSourceFile (
95+ outerPath: outerPath,
96+ target: target,
97+ to: & auxiliaryFiles
10398 )
10499
100+ if !manifest. description. contains ( " swift-syntax " ) {
101+ newPackageCall = try AddPackageDependency
102+ . addPackageDependencyLocal (
103+ . swiftSyntax(
104+ configuration: installedSwiftPMConfiguration
105+ ) ,
106+ to: newPackageCall
107+ )
108+
109+ // Look for the first import declaration and insert an
110+ // import of `CompilerPluginSupport` there.
111+ let newImport = " import CompilerPluginSupport \n "
112+ for node in manifest. statements {
113+ if let importDecl = node. item. as ( ImportDeclSyntax . self) {
114+ let insertPos = importDecl
115+ . positionAfterSkippingLeadingTrivia
116+ extraManifestEdits. append (
117+ SourceEdit (
118+ range: insertPos..< insertPos,
119+ replacement: newImport
120+ )
121+ )
122+ break
123+ }
124+ }
125+ }
126+
105127 default : break ;
106128 }
107129
108130 return PackageEditResult (
109- manifestEdits: manifestEdits,
131+ manifestEdits: [
132+ . replace( packageCall, with: newPackageCall. description)
133+ ] + extraManifestEdits,
110134 auxiliaryFiles: auxiliaryFiles
111135 )
112136 }
@@ -191,6 +215,30 @@ public struct AddTarget {
191215 sourceCode: sourceFileText
192216 )
193217 }
218+
219+ /// Add a file that introduces the main entrypoint and provided macros
220+ /// for a macro target.
221+ fileprivate static func addProvidedMacrosSourceFile(
222+ outerPath: RelativePath ,
223+ target: TargetDescription ,
224+ to auxiliaryFiles: inout AuxiliaryFiles
225+ ) {
226+ auxiliaryFiles. addSourceFile (
227+ path: outerPath. appending (
228+ components: [ target. name, " ProvidedMacros.swift " ]
229+ ) ,
230+ sourceCode: """
231+ import SwiftCompilerPlugin
232+
233+ @main
234+ struct \( raw: target. name) Macros: CompilerPlugin {
235+ let providingMacros: [Macro.Type] = [
236+ \( raw: target. name) .self,
237+ ]
238+ }
239+ """
240+ )
241+ }
194242}
195243
196244fileprivate extension TargetDescription . Dependency {
@@ -225,3 +273,28 @@ fileprivate let macroTargetDependencies: [TargetDescription.Dependency] = [
225273 . product( name: " SwiftCompilerPlugin " , package : " swift-syntax " ) ,
226274 . product( name: " SwiftSyntaxMacros " , package : " swift-syntax " ) ,
227275]
276+
277+ /// The package dependency for swift-syntax, for use in macros.
278+ fileprivate extension PackageDependency {
279+ /// Source control URL for the swift-syntax package.
280+ static var swiftSyntaxURL : SourceControlURL {
281+ " https://github.com/apple/swift-syntax.git "
282+ }
283+
284+ /// Package dependency on the swift-syntax package.
285+ static func swiftSyntax(
286+ configuration: InstalledSwiftPMConfiguration
287+ ) -> PackageDependency {
288+ let swiftSyntaxVersionDefault = configuration
289+ . swiftSyntaxVersionForMacroTemplate
290+ let swiftSyntaxVersion = Version ( swiftSyntaxVersionDefault. description) !
291+
292+ return . sourceControl(
293+ identity: PackageIdentity ( url: swiftSyntaxURL) ,
294+ nameForTargetDependencyResolutionOnly: nil ,
295+ location: . remote( swiftSyntaxURL) ,
296+ requirement: . range( . upToNextMajor( from: swiftSyntaxVersion) ) ,
297+ productFilter: . everything
298+ )
299+ }
300+ }
0 commit comments