in src/Tulsi/TulsiGeneratorConfigDocument.swift [438:554]
func updateSourcePaths(_ callback: @escaping ([UISourcePath]) -> Void) {
var sourcePathMap = [String: UISourcePath]()
selectedSourcePaths.forEach() { sourcePathMap[$0.path] = $0 }
processingTaskStarted()
let selectedLabels = self.selectedRuleInfos.map() { $0.label }
let optionSet = self.optionSet!
Thread.doOnQOSUserInitiatedThread() {
defer {
Thread.doOnMainQueue() {
self.sourcePaths = [UISourcePath](sourcePathMap.values)
callback(self.sourcePaths)
self.processingTaskFinished()
}
}
let ruleEntryMap: RuleEntryMap
do {
let startupOptions = optionSet[.BazelBuildStartupOptionsDebug]
let extraStartupOptions = optionSet[.ProjectGenerationBazelStartupOptions]
let buildOptions = optionSet[.BazelBuildOptionsDebug]
let compilationModeOption = optionSet[.ProjectGenerationCompilationMode]
let platformConfigOption = optionSet[.ProjectGenerationPlatformConfiguration]
let prioritizeSwiftOption = optionSet[.ProjectPrioritizesSwift]
let use64BitWatchSimulatorOption = optionSet[.Use64BitWatchSimulator]
ruleEntryMap = try self.infoExtractor.ruleEntriesForLabels(selectedLabels,
startupOptions: startupOptions,
extraStartupOptions: extraStartupOptions,
buildOptions: buildOptions,
compilationModeOption: compilationModeOption,
platformConfigOption: platformConfigOption,
prioritizeSwiftOption: prioritizeSwiftOption,
use64BitWatchSimulatorOption: use64BitWatchSimulatorOption,
features: self.enabledFeatures(options: optionSet))
} catch TulsiProjectInfoExtractor.ExtractorError.ruleEntriesFailed(let info) {
LogMessage.postError("Label resolution failed: \(info)")
return
} catch let e {
LogMessage.postError("Label resolution failed. \(e)")
return
}
var unresolvedLabels = Set<BuildLabel>()
var sourceRuleEntries = [RuleEntry]()
for label in selectedLabels {
let ruleEntries = ruleEntryMap.ruleEntries(buildLabel: label)
if ruleEntries.isEmpty {
unresolvedLabels.insert(label)
} else {
sourceRuleEntries.append(contentsOf: ruleEntries)
}
}
if !unresolvedLabels.isEmpty {
let fmt = NSLocalizedString("Warning_LabelResolutionFailed",
comment: "A non-critical failure to restore some Bazel labels when loading a document. Details are provided as %1$@.")
LogMessage.postWarning(String(format: fmt,
"Missing labels: \(unresolvedLabels.map({$0.description}))"))
}
var selectedRuleEntries = [RuleEntry]()
for selectedRuleInfo in self.selectedRuleInfos {
selectedRuleEntries.append(contentsOf: ruleEntryMap.ruleEntries(buildLabel: selectedRuleInfo.label))
}
var processedEntries = Set<RuleEntry>()
let componentDelimiters = CharacterSet(charactersIn: "/:")
func addPath(_ path: String) {
let path = (path as NSString).deletingLastPathComponent
if path.isEmpty { return }
let pathComponents = path.components(separatedBy: componentDelimiters)
var cumulativePathComponents = [String]()
for component in pathComponents {
cumulativePathComponents.append(component)
let componentPath = cumulativePathComponents.joined(separator: "/")
cumulativePathComponents = [componentPath]
if sourcePathMap[componentPath] == nil {
sourcePathMap[componentPath] = UISourcePath(path: componentPath)
}
}
}
func extractSourcePaths(_ ruleEntry: RuleEntry) {
if processedEntries.contains(ruleEntry) {
// Rules that have already been processed will already have all of their transitive
// sources captured.
return
}
processedEntries.insert(ruleEntry)
for dep in ruleEntry.dependencies {
guard let depRuleEntry = ruleEntryMap.ruleEntry(buildLabel: dep, depender: ruleEntry) else {
// Some dependencies are expected to be unresolved, e.g., those that rely on implicit
// outputs of other rules.
continue
}
extractSourcePaths(depRuleEntry)
}
for fileInfo in ruleEntry.projectArtifacts {
addPath(fileInfo.fullPath)
}
}
var sourceTargets = [BuildLabel]()
for entry in sourceRuleEntries {
extractSourcePaths(entry)
sourceTargets.append(entry.label)
}
let buildfiles = self.infoExtractor.extractBuildfiles(sourceTargets)
for buildfileLabel in buildfiles {
guard let path = buildfileLabel.asFileName else { continue }
addPath(path)
}
}
}