@@ -84,6 +84,81 @@ class SourceGeneratorTests: XCTestCase {
8484 try pbxProj. expectFile ( paths: [ " Sources " , " A " , " C2.0 " , " c.swift " ] , buildPhase: . sources)
8585 }
8686
87+ $0. it ( " generates a single parent for groups when a source is the base path " ) {
88+ let directories = """
89+ Module:
90+ - Extension:
91+ - a.swift
92+ - Model:
93+ - b.swift
94+ - c.swift
95+ """
96+ try createDirectories ( directories)
97+
98+ let target = Target ( name: " Module " , type: . framework, platform: . iOS, sources: [ " ../Module " ] )
99+ let project = Project ( basePath: directoryPath + " Module " , name: " Module " , targets: [ target] )
100+
101+ let generator = PBXProjGenerator ( project: project, projectDirectory: directoryPath)
102+ let pbxProj = try generator. generate ( )
103+
104+ try pbxProj. expectFile ( paths: [ " Module " , " Extension " , " a.swift " ] , buildPhase: . sources)
105+ try pbxProj. expectFile ( paths: [ " Module " , " Model " , " b.swift " ] , buildPhase: . sources)
106+ try pbxProj. expectFile ( paths: [ " Module " , " c.swift " ] , buildPhase: . sources)
107+ try expectSingleParents ( pbxProj)
108+
109+ let mainGroupChildren = try pbxProj. getMainGroup ( ) . children. map ( \. nameOrPath)
110+ try expect ( mainGroupChildren. contains ( " Extension " ) ) == false
111+ try expect ( mainGroupChildren. contains ( " Model " ) ) == false
112+ }
113+
114+ $0. it ( " generates a single parent for a group first referenced as a top level file source " ) {
115+ let directories = """
116+ Sources:
117+ - Pages:
118+ - a.swift
119+ - b.swift
120+ """
121+ try createDirectories ( directories)
122+
123+ // The file source creates Pages at the top level before the directory source reparents it.
124+ let fileTarget = Target ( name: " A " , type: . application, platform: . iOS, sources: [ " Sources/Pages/a.swift " ] )
125+ let directoryTarget = Target ( name: " B " , type: . application, platform: . iOS, sources: [ " Sources " ] )
126+ let project = Project ( basePath: directoryPath, name: " Test " , targets: [ fileTarget, directoryTarget] )
127+
128+ let pbxProj = try project. generatePbxProj ( )
129+
130+ try pbxProj. expectFile ( paths: [ " Sources " , " Pages " , " a.swift " ] , buildPhase: . sources)
131+ try pbxProj. expectFile ( paths: [ " Sources " , " b.swift " ] , buildPhase: . sources)
132+ try expectSingleParents ( pbxProj)
133+
134+ let mainGroupChildren = try pbxProj. getMainGroup ( ) . children. map ( \. nameOrPath)
135+ try expect ( mainGroupChildren. contains ( " Sources/Pages " ) ) == false
136+ }
137+
138+ $0. it ( " keeps a subdirectory reachable when the base source excludes it and another source adds it " ) {
139+ let directories = """
140+ Module:
141+ - Resources:
142+ - a.json
143+ - b.swift
144+ """
145+ try createDirectories ( directories)
146+
147+ // The excluded directory is skipped by its parent, then populated through a later source.
148+ let target = Target ( name: " Module " , type: . framework, platform: . iOS, sources: [
149+ TargetSource ( path: " ../Module " , excludes: [ " Resources/** " ] ) ,
150+ TargetSource ( path: " Resources " , buildPhase: . resources) ,
151+ ] )
152+ let project = Project ( basePath: directoryPath + " Module " , name: " Module " , targets: [ target] )
153+
154+ let generator = PBXProjGenerator ( project: project, projectDirectory: directoryPath)
155+ let pbxProj = try generator. generate ( )
156+
157+ try pbxProj. expectFile ( paths: [ " Module " , " b.swift " ] , buildPhase: . sources)
158+ try pbxProj. expectFile ( paths: [ " Module/Resources " , " a.json " ] , names: [ " Resources " , " a.json " ] , buildPhase: . resources)
159+ try expectSingleParents ( pbxProj)
160+ }
161+
87162 $0. it ( " generates synced folder " ) {
88163 let directories = """
89164 Sources:
0 commit comments