@@ -163,8 +163,22 @@ final class ProjectDetailViewModel: ObservableObject {
163163 url. contains ( " /deriveddata/ " ) && url. contains ( " /sourcepackages/ " )
164164 }
165165
166+ /// Checks if a warning is from a generated or system source (e.g., Swift macros, SDK headers).
167+ func isGeneratedSource( _ warning: Notice ) -> Bool {
168+ let url = warning. documentURL. lowercased ( )
169+ return url. contains ( " /var/folders/ " ) ||
170+ url. contains ( " swift-generated-sources " ) ||
171+ url. contains ( " @__swiftmacro_ " ) ||
172+ url. contains ( " /library/developer/xcode/deriveddata/ " ) ||
173+ url. contains ( " .framework/headers/ " )
174+ }
175+
166176 private func buildDirectoryTree( ) -> [ DirectoryNode ] {
167- let projectWarnings = activeFilteredWarnings. filter { !isPackageDependency( $0) && !$0. documentURL. isEmpty }
177+ let projectWarnings = activeFilteredWarnings. filter {
178+ !isPackageDependency( $0) &&
179+ !$0. documentURL. isEmpty &&
180+ !isGeneratedSource( $0)
181+ }
168182 guard !projectWarnings. isEmpty else { return [ ] }
169183
170184 // Count warnings per file (not directory)
@@ -242,7 +256,12 @@ final class ProjectDetailViewModel: ObservableObject {
242256 var currentPath = commonPrefix
243257
244258 for (index, component) in components. enumerated ( ) {
245- currentPath += " / " + component
259+ // Avoid double slashes when commonPrefix is just "/"
260+ if currentPath == " / " {
261+ currentPath = " / " + component
262+ } else {
263+ currentPath += " / " + component
264+ }
246265 let isLastComponent = index == components. count - 1
247266 currentNode = currentNode. getOrCreateChild (
248267 name: component,
@@ -256,14 +275,38 @@ final class ProjectDetailViewModel: ObservableObject {
256275 }
257276 }
258277
259- return rootContainer. children. values
278+ var topLevelNodes = rootContainer. children. values
260279 . map { $0. toDirectoryNode ( ) }
261280 . sorted {
262281 if $0. warningCount != $1. warningCount {
263282 return $0. warningCount > $1. warningCount
264283 }
265284 return $0. name < $1. name
266285 }
286+
287+ // Collapse single-child chains to start at the first meaningful branching point
288+ topLevelNodes = collapseSingleChildChains ( topLevelNodes)
289+
290+ return topLevelNodes
291+ }
292+
293+ /// Collapses single-child directory chains to show the first meaningful branching point.
294+ /// For example: Users/g.halverson/Dev/project with one child each becomes just "project".
295+ private func collapseSingleChildChains( _ nodes: [ DirectoryNode ] ) -> [ DirectoryNode ] {
296+ // If we have exactly one node and it has children, check if we should skip it
297+ guard nodes. count == 1 ,
298+ let singleNode = nodes. first,
299+ !singleNode. children. isEmpty else {
300+ return nodes
301+ }
302+
303+ // If this single node has multiple children, this is our branching point - return it
304+ if singleNode. children. count > 1 {
305+ return nodes
306+ }
307+
308+ // Single node with single child - recurse to collapse further
309+ return collapseSingleChildChains ( singleNode. children)
267310 }
268311
269312 private func getFilePath( from documentURL: String ) -> String {
0 commit comments