@@ -5,9 +5,27 @@ import Testing
55
66/// Harness for extracting and testing documentation code examples
77internal class DocumentationTestHarness {
8+ /// Project root directory calculated from the current file location
9+ private static let projectRoot : URL = {
10+ let currentFileURL = URL ( fileURLWithPath: #file)
11+ return currentFileURL
12+ . deletingLastPathComponent ( ) // Tests/SyntaxDocTests
13+ . deletingLastPathComponent ( ) // Tests
14+ . deletingLastPathComponent ( ) // Project root
15+ } ( )
16+
17+ /// Document paths to search for documentation files
18+ private static let docPaths = [
19+ " Sources/SyntaxKit/Documentation.docc " ,
20+ " README.md " ,
21+ " Examples " ,
22+ ]
23+
24+ /// Default file extensions for documentation files
25+ private static let defaultPathExtensions = [ " md " ]
826 /// Validates all code examples in all documentation files
927 internal func validateAllExamples( ) async throws -> [ ValidationResult ] {
10- let documentationFiles = try findDocumentationFiles ( )
28+ let documentationFiles = try DocumentationTestHarness . findDocumentationFiles ( )
1129 var allResults : [ ValidationResult ] = [ ]
1230
1331 for filePath in documentationFiles {
@@ -362,54 +380,9 @@ internal class DocumentationTestHarness {
362380 #endif
363381
364382 /// Finds all documentation files containing code examples
365- private func findDocumentationFiles( ) throws -> [ String ] {
366- let currentFileURL = URL ( fileURLWithPath: #file)
367- let projectRoot =
368- currentFileURL
369- . deletingLastPathComponent ( ) // Tests/SyntaxKitTests/Integration
370- . deletingLastPathComponent ( ) // Tests/SyntaxKitTests
371- . deletingLastPathComponent ( ) // Tests
372- . deletingLastPathComponent ( ) // Project root
373- let docPaths = [
374- " Sources/SyntaxKit/Documentation.docc " ,
375- " README.md " ,
376- " Examples " ,
377- ]
378-
379- var documentationFiles : [ String ] = [ ]
380-
381- for docPath in docPaths {
382- let fullPath = projectRoot. appendingPathComponent ( docPath)
383-
384- if FileManager . default. fileExists ( atPath: fullPath. path) {
385- if docPath. hasSuffix ( " .md " ) {
386- documentationFiles. append ( docPath)
387- } else {
388- // Recursively find .md files in directory
389- let foundFiles = try findMarkdownFiles ( in: fullPath, relativeTo: projectRoot)
390- documentationFiles. append ( contentsOf: foundFiles)
391- }
392- }
393- }
394-
395- return documentationFiles
396- }
397-
398- /// Recursively finds markdown files in a directory
399- private func findMarkdownFiles( in directory: URL , relativeTo root: URL ) throws -> [ String ] {
400- let fileManager = FileManager . default
401- let enumerator = fileManager. enumerator ( at: directory, includingPropertiesForKeys: nil )
402-
403- var markdownFiles : [ String ] = [ ]
404-
405- while let fileURL = enumerator? . nextObject ( ) as? URL {
406- if fileURL. pathExtension == " md " {
407- let relativePath = String ( fileURL. path. dropFirst ( root. path. count + 1 ) )
408- markdownFiles. append ( relativePath)
409- }
410- }
411-
412- return markdownFiles
383+ @available ( * , deprecated, message: " Use findDocumentationFiles(in:relativeTo:pathExtensions:) instead " )
384+ private static func findDocumentationFiles( ) throws -> [ String ] {
385+ try FileManager . default. findDocumentationFiles ( in: Self . docPaths, relativeTo: Self . projectRoot, pathExtensions: Self . defaultPathExtensions)
413386 }
414387
415388 /// Resolves a relative file path to absolute path (public for use by test methods)
@@ -419,28 +392,10 @@ internal class DocumentationTestHarness {
419392
420393 /// Resolves a relative file path to absolute path
421394 private func resolveFilePath( _ filePath: String ) throws -> String {
422- let currentFileURL : URL
423-
424- // Handle #file which might be relative or absolute
425- if #filePath. hasPrefix ( " / " ) {
426- // #file is already absolute
427- currentFileURL = URL ( fileURLWithPath: #filePath)
428- } else {
429- // #file is relative, resolve it from current working directory
430- currentFileURL = URL ( fileURLWithPath: FileManager . default. currentDirectoryPath)
431- . appendingPathComponent ( #filePath)
432- }
433-
434- let projectRoot =
435- currentFileURL
436- . deletingLastPathComponent ( ) // Tests/SyntaxDocTests
437- . deletingLastPathComponent ( ) // Tests
438- . deletingLastPathComponent ( ) // Project root
439-
440395 if filePath. hasPrefix ( " / " ) {
441396 return filePath
442397 } else {
443- return projectRoot. appendingPathComponent ( filePath) . path
398+ return Self . projectRoot. appendingPathComponent ( filePath) . path
444399 }
445400 }
446401}
0 commit comments