Skip to content

Add ability to specify which files should be included and excluded when documenting a module. #699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 54 additions & 10 deletions Source/SourceKittenFramework/Module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ public struct Module {
package if `nil`.
- parameter path: Path of the directory containing the SPM `.build` directory.
Uses the current directory by default.
- parameter include: Source file pathnames to be included in documentation. Supports wildcards. Empty array will include all files.
- parameter exclude: Source file pathnames to be excluded from documentation. Supports wildcards.
*/
public init?(spmName: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath) {
public init?(spmName: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath, include: [String] = [], exclude: [String] = []) {
let yamlPath = URL(fileURLWithPath: path).appendingPathComponent(".build/debug.yaml").path
guard let yaml = try? Yams.compose(yaml: String(contentsOfFile: yamlPath, encoding: .utf8)),
let commands = (yaml as Node?)?["commands"]?.mapping?.values else {
Expand Down Expand Up @@ -76,7 +78,7 @@ public struct Module {
arguments.append(contentsOf: imports)
return arguments
}()
sourceFiles = sources
sourceFiles = sources.filteringElements(include: include, exclude: exclude)
}

/**
Expand All @@ -89,8 +91,10 @@ public struct Module {
package if `nil`.
- parameter path: Path of the directory containing the `Package.swift` file.
Uses the current directory by default.
- parameter include: Source file pathnames to be included in documentation. Supports wildcards. Empty array will include all files.
- parameter exclude: Source file pathnames to be excluded from documentation. Supports wildcards.
*/
public init?(spmArguments: [String], spmName: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath) {
public init?(spmArguments: [String], spmName: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath, include: [String] = [], exclude: [String] = []) {
fputs("Running swift build\n", stderr)
let buildResults = Exec.run("/usr/bin/env", ["swift", "build"] + spmArguments, currentDirectory: path, stderr: .merge)
guard buildResults.terminationStatus == 0 else {
Expand All @@ -100,7 +104,7 @@ public struct Module {
return nil
}

self.init(spmName: spmName, inPath: path)
self.init(spmName: spmName, inPath: path, include: include, exclude: exclude)
}

/**
Expand All @@ -110,8 +114,10 @@ public struct Module {
- parameter xcodeBuildArguments: The arguments necessary pass in to `xcodebuild` to build this Module.
- parameter name: Module name. Will be parsed from `xcodebuild` output if nil.
- parameter path: Path to run `xcodebuild` from. Uses current path by default.
- parameter include: Source file pathnames to be included in documentation. Supports wildcards. Empty array will include all files.
- parameter exclude: Source file pathnames to be excluded from documentation. Supports wildcards.
*/
public init?(xcodeBuildArguments: [String], name: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath) {
public init?(xcodeBuildArguments: [String], name: String? = nil, inPath path: String = FileManager.default.currentDirectoryPath, include: [String] = [], exclude: [String] = []) {
let buildSettings = XcodeBuild.showBuildSettings(arguments: xcodeBuildArguments, inPath: path)

let name = name
Expand All @@ -132,15 +138,15 @@ public struct Module {
if let output = results.string,
let arguments = parseCompilerArguments(xcodebuildOutput: output, language: .swift, moduleName: name),
let moduleName = moduleName(fromArguments: arguments) {
self.init(name: moduleName, compilerArguments: arguments)
self.init(name: moduleName, compilerArguments: arguments, include: include, exclude: exclude)
return
}
// Check New Build System is used
fputs("Checking xcodebuild -showBuildSettings\n", stderr)
if let projectTempRoot = buildSettings?.firstBuildSettingValue(for: { $0.PROJECT_TEMP_ROOT }),
let arguments = checkNewBuildSystem(in: projectTempRoot, moduleName: name),
let moduleName = moduleName(fromArguments: arguments) {
self.init(name: moduleName, compilerArguments: arguments)
self.init(name: moduleName, compilerArguments: arguments, include: include, exclude: exclude)
return
}
// Executing `clean build` is a fallback.
Expand All @@ -157,23 +163,25 @@ public struct Module {
fputs("Could not parse module name from compiler arguments.\n", stderr)
return nil
}
self.init(name: moduleName, compilerArguments: arguments)
self.init(name: moduleName, compilerArguments: arguments, include: include, exclude: exclude)
}

/**
Initializer to create a Module by name and compiler arguments.

- parameter name: Module name.
- parameter compilerArguments: Compiler arguments required by SourceKit to process the source files in this Module.
- parameter include: Source file pathnames to be included in documentation. Supports wildcards. Empty array will include all files.
- parameter exclude: Source file pathnames to be excluded from documentation. Supports wildcards.
*/
public init(name: String, compilerArguments: [String]) {
public init(name: String, compilerArguments: [String], include: [String] = [], exclude: [String] = []) {
self.name = name
self.compilerArguments = compilerArguments.expandingResponseFiles
sourceFiles = self.compilerArguments.filter({
$0.bridge().isSwiftFile() && $0.isFile
}).map {
return URL(fileURLWithPath: $0).resolvingSymlinksInPath().path
}
}.filteringElements(include: include, exclude: exclude)
}
}

Expand Down Expand Up @@ -202,3 +210,39 @@ private extension Collection where Element == XcodeBuildSetting {
return lazy.compactMap(getterClosure).first
}
}


private extension Array where Element == String {

func filteringElements(include: [String], exclude: [String]) -> [String] {
var result = self
if !include.isEmpty {
result = result.filter { file in
for pattern in include {
if file.matches(pattern: pattern) {
return true
}
}
return false
}
}

result = result.filter { file in
for pattern in exclude {
if file.matches(pattern: pattern) {
return false
}
}
return true
}
return result
}
}

private extension String {

func matches(pattern: String) -> Bool {
let pred = NSPredicate(format: "self LIKE %@", pattern)
return !NSArray(object: self).filtered(using: pred).isEmpty
}
}
8 changes: 6 additions & 2 deletions Source/sourcekitten/Doc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ extension SourceKitten {
var singleFile: Bool = false
@Option(help: "Name of Swift module to document (can't be used with `--single-file`)")
var moduleName: String = ""
@Option(help: "Source file pathnames to be included in documentation. Supports wildcards. (can't be used with `--single-file`)")
var include: [String] = []
@Option(help: "Source file pathnames to be excluded from documentation. Supports wildcards. (can't be used with `--single-file`)")
var exclude: [String] = []
@Flag(help: "Document a Swift Package Manager module")
var spm: Bool = false
@Flag(help: "Document Objective-C headers instead of Swift code")
Expand All @@ -21,7 +25,7 @@ extension SourceKitten {
let moduleName = self.moduleName.isEmpty ? nil : self.moduleName

if spm {
if let docs = Module(spmArguments: arguments, spmName: moduleName)?.docs {
if let docs = Module(spmArguments: arguments, spmName: moduleName, include: include, exclude: exclude)?.docs {
print(docs)
return
}
Expand Down Expand Up @@ -55,7 +59,7 @@ extension SourceKitten {
throw SourceKittenError.readFailed(path: arguments[0])
}

let module = Module(xcodeBuildArguments: arguments, name: moduleName)
let module = Module(xcodeBuildArguments: arguments, name: moduleName, include: include, exclude: exclude)
if let docs = module?.docs {
print(docs)
return
Expand Down