Skip to content

Commit a1b85b0

Browse files
authored
Merge pull request #55 from DougGregor/emit-doc-with-module
Emitting a module implies emitting module documentation.
2 parents 2f5e894 + e95fe6b commit a1b85b0

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ public struct Driver {
250250
self.objcGeneratedHeaderPath = try Self.computeSupplementaryOutputPath(&parsedOptions, type: .objcHeader, isOutput: .emit_objc_header, outputPath: .emit_objc_header_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
251251
self.loadedModuleTracePath = try Self.computeSupplementaryOutputPath(&parsedOptions, type: .moduleTrace, isOutput: .emit_loaded_module_trace, outputPath: .emit_loaded_module_trace_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
252252
self.tbdPath = try Self.computeSupplementaryOutputPath(&parsedOptions, type: .tbd, isOutput: .emit_tbd, outputPath: .emit_tbd_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
253-
self.moduleDocOutputPath = try Self.computeSupplementaryOutputPath(&parsedOptions, type: .swiftDocumentation, isOutput: .emit_module_doc, outputPath: .emit_module_doc_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
253+
self.moduleDocOutputPath = try Self.computeModuleDocOutputPath(&parsedOptions, moduleOutputPath: self.moduleOutput?.outputPath, compilerOutputType: compilerOutputType, moduleName: moduleName)
254254
self.swiftInterfacePath = try Self.computeSupplementaryOutputPath(&parsedOptions, type: .swiftInterface, isOutput: .emit_module_interface, outputPath: .emit_module_interface_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
255255
self.optimizationRecordPath = try Self.computeSupplementaryOutputPath(&parsedOptions, type: .optimizationRecord, isOutput: .save_optimization_record, outputPath: .save_optimization_record_path, compilerOutputType: compilerOutputType, moduleName: moduleName)
256256
}
@@ -919,7 +919,8 @@ extension Driver {
919919
isOutput: Option?,
920920
outputPath: Option,
921921
compilerOutputType: FileType?,
922-
moduleName: String
922+
moduleName: String,
923+
patternOutputFile: VirtualPath? = nil
923924
) throws -> VirtualPath? {
924925
// FIXME: Do we need to check the output file map?
925926

@@ -946,17 +947,56 @@ extension Driver {
946947
return path
947948
}
948949

949-
// Otherwise, put this output alongside the requested output.
950-
let pathString: String
951-
if let ext = path.extension {
952-
pathString = String(path.name.dropLast(ext.count + 1))
953-
} else {
954-
pathString = path.name
950+
return try path.replacingExtension(with: type)
951+
}
952+
953+
return try VirtualPath(path: moduleName.appendingFileTypeExtension(type))
954+
}
955+
956+
/// Determine the output path for a module documentation.
957+
static func computeModuleDocOutputPath(
958+
_ parsedOptions: inout ParsedOptions,
959+
moduleOutputPath: VirtualPath?,
960+
compilerOutputType: FileType?,
961+
moduleName: String
962+
) throws -> VirtualPath? {
963+
// FIXME: Do we need to check the output file map?
964+
965+
// If there is an explicit argument for the output path, use that
966+
if let outputPathArg = parsedOptions.getLastArgument(.emit_module_doc_path) {
967+
// Consume -emit-module-doc if it's there.
968+
_ = parsedOptions.hasArgument(.emit_module_doc)
969+
970+
return try VirtualPath(path: outputPathArg.asSingle)
971+
}
972+
973+
// If there's a known module output path, put the .swiftdoc file next
974+
// to it.
975+
if let moduleOutputPath = moduleOutputPath {
976+
// Consume -emit-module-doc if it's there.
977+
_ = parsedOptions.hasArgument(.emit_module_doc)
978+
979+
return try moduleOutputPath.replacingExtension(with: .swiftDocumentation)
980+
}
981+
982+
// If not specifically asked to emit Swift module documentation, don't.
983+
if !parsedOptions.hasArgument(.emit_module_doc) {
984+
return nil
985+
}
986+
987+
// If there is an output argument, derive the name from there.
988+
if let outputPathArg = parsedOptions.getLastArgument(.o) {
989+
let path = try VirtualPath(path: outputPathArg.asSingle)
990+
991+
// If the compiler output is of this type, use the argument directly.
992+
if compilerOutputType == .swiftDocumentation {
993+
return path
955994
}
956995

957-
return try VirtualPath(path: pathString.appendingFileTypeExtension(type))
996+
// Otherwise, put this output alongside the requested output.
997+
return try path.replacingExtension(with: .swiftDocumentation)
958998
}
959999

960-
return try VirtualPath(path: moduleName.appendingFileTypeExtension(type))
1000+
return try VirtualPath(path: moduleName.appendingFileTypeExtension(.swiftDocumentation))
9611001
}
9621002
}

Sources/SwiftDriver/Utilities/VirtualPath.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,18 @@ extension VirtualPath: Codable {
131131
}
132132
}
133133
}
134+
135+
extension VirtualPath {
136+
/// Replace the extension of the given path with a new one based on the
137+
/// specified file type.
138+
public func replacingExtension(with fileType: FileType) throws -> VirtualPath {
139+
let pathString: String
140+
if let ext = self.extension {
141+
pathString = String(name.dropLast(ext.count + 1))
142+
} else {
143+
pathString = name
144+
}
145+
146+
return try VirtualPath(path: pathString.appendingFileTypeExtension(fileType))
147+
}
148+
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,5 +317,14 @@ final class SwiftDriverTests: XCTestCase {
317317
XCTAssertEqual(plannedJobs1[2].outputs[0], VirtualPath.relative(RelativePath("Test.swiftmodule")))
318318
XCTAssertEqual(plannedJobs1[2].outputs[1], VirtualPath.absolute(AbsolutePath("/foo/bar/Test.swiftdoc")))
319319
XCTAssert(plannedJobs1[2].commandLine.contains(.flag("-import-objc-header")))
320+
321+
var driver2 = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "-module-name", "Test", "-emit-module-path", "/foo/bar/Test.swiftmodule" ])
322+
let plannedJobs2 = try driver2.planBuild()
323+
XCTAssertEqual(plannedJobs2.count, 3)
324+
XCTAssertTrue(plannedJobs2[2].tool.name.contains("swift"))
325+
XCTAssertEqual(plannedJobs2[2].outputs.count, 2)
326+
XCTAssertEqual(plannedJobs2[2].outputs[0], VirtualPath.absolute(AbsolutePath("/foo/bar/Test.swiftmodule")))
327+
XCTAssertEqual(plannedJobs2[2].outputs[1], VirtualPath.absolute(AbsolutePath("/foo/bar/Test.swiftdoc")))
328+
320329
}
321330
}

0 commit comments

Comments
 (0)