Skip to content

Commit 0b32801

Browse files
authored
convert the PackageLoading module to the new diagnostics apis (#3754)
motivation: adapt new diagnostics apis changes: refactor the PackageLoading module to use new diagnostics api
1 parent 8473930 commit 0b32801

File tree

3 files changed

+56
-30
lines changed

3 files changed

+56
-30
lines changed

Sources/PackageLoading/ModuleMapGenerator.swift

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
import TSCBasic
12-
import PackageModel
11+
import Basics
1312
import Foundation
13+
import PackageModel
14+
import TSCBasic
1415

1516
/// Name of the module map file recognized by the Clang and Swift compilers.
1617
public let moduleMapFilename = "module.modulemap"
@@ -86,8 +87,14 @@ public struct ModuleMapGenerator {
8687
}
8788

8889
/// Inspects the file system at the public-headers directory with which the module map generator was instantiated, and returns the type of module map that applies to that directory. This function contains all of the heuristics that implement module map policy for package targets; other functions just use the results of this determination.
89-
public func determineModuleMapType(diagnostics: DiagnosticsEngine) -> ModuleMapType {
90+
public func determineModuleMapType(observabilityScope: ObservabilityScope) -> ModuleMapType {
9091
// The following rules are documented at https://github.com/apple/swift-package-manager/blob/master/Documentation/Usage.md#creating-c-language-targets. To avoid breaking existing packages, do not change the semantics here without making any change conditional on the tools version of the package that defines the target.
92+
93+
let diagnosticsEmitter = observabilityScope.makeDiagnosticsEmitter {
94+
var metadata = ObservabilityMetadata()
95+
metadata.targetName = self.targetName
96+
return metadata
97+
}
9198

9299
// First check for a custom module map.
93100
let customModuleMapFile = publicHeadersDir.appending(component: moduleMapFilename)
@@ -97,7 +104,7 @@ public struct ModuleMapGenerator {
97104

98105
// Warn if the public-headers directory is missing. For backward compatibility reasons, this is not an error, we just won't generate a module map in that case.
99106
guard fileSystem.exists(publicHeadersDir) else {
100-
diagnostics.emit(.missingPublicHeadersDirectory(targetName: targetName, publicHeadersDir: publicHeadersDir))
107+
diagnosticsEmitter.emit(.missingPublicHeadersDirectory(targetName: targetName, publicHeadersDir: publicHeadersDir))
101108
return .none
102109
}
103110

@@ -108,7 +115,7 @@ public struct ModuleMapGenerator {
108115
}
109116
catch {
110117
// This might fail because of a file system error, etc.
111-
diagnostics.emit(.inaccessiblePublicHeadersDirectory(targetName: targetName, publicHeadersDir: publicHeadersDir, fileSystemError: error))
118+
diagnosticsEmitter.emit(.inaccessiblePublicHeadersDirectory(targetName: targetName, publicHeadersDir: publicHeadersDir, fileSystemError: error))
112119
return .none
113120
}
114121

@@ -122,7 +129,7 @@ public struct ModuleMapGenerator {
122129
if fileSystem.isFile(umbrellaHeader) {
123130
// In this case, 'PublicHeadersDir' is expected to contain no subdirectories.
124131
if directories.count != 0 {
125-
diagnostics.emit(.umbrellaHeaderHasSiblingDirectories(targetName: targetName, umbrellaHeader: umbrellaHeader, siblingDirs: directories))
132+
diagnosticsEmitter.emit(.umbrellaHeaderHasSiblingDirectories(targetName: targetName, umbrellaHeader: umbrellaHeader, siblingDirs: directories))
126133
return .none
127134
}
128135
return .umbrellaHeader(umbrellaHeader)
@@ -131,20 +138,20 @@ public struct ModuleMapGenerator {
131138
/// Check for the common mistake of naming the umbrella header 'TargetName.h' instead of 'ModuleName.h'.
132139
let misnamedUmbrellaHeader = publicHeadersDir.appending(component: targetName + ".h")
133140
if fileSystem.isFile(misnamedUmbrellaHeader) {
134-
diagnostics.emit(.misnamedUmbrellaHeader(misnamedUmbrellaHeader: misnamedUmbrellaHeader, umbrellaHeader: umbrellaHeader))
141+
diagnosticsEmitter.emit(.misnamedUmbrellaHeader(misnamedUmbrellaHeader: misnamedUmbrellaHeader, umbrellaHeader: umbrellaHeader))
135142
}
136143

137144
// If 'PublicHeadersDir/ModuleName/ModuleName.h' exists, then use it as the umbrella header.
138145
let nestedUmbrellaHeader = publicHeadersDir.appending(components: moduleName, moduleName + ".h")
139146
if fileSystem.isFile(nestedUmbrellaHeader) {
140147
// In this case, 'PublicHeadersDir' is expected to contain no subdirectories other than 'ModuleName'.
141148
if directories.count != 1 {
142-
diagnostics.emit(.umbrellaHeaderParentDirHasSiblingDirectories(targetName: targetName, umbrellaHeader: nestedUmbrellaHeader, siblingDirs: directories.filter{ $0.basename != moduleName }))
149+
diagnosticsEmitter.emit(.umbrellaHeaderParentDirHasSiblingDirectories(targetName: targetName, umbrellaHeader: nestedUmbrellaHeader, siblingDirs: directories.filter{ $0.basename != moduleName }))
143150
return .none
144151
}
145152
// In this case, 'PublicHeadersDir' is also expected to contain no header files.
146153
if headers.count != 0 {
147-
diagnostics.emit(.umbrellaHeaderParentDirHasSiblingHeaders(targetName: targetName, umbrellaHeader: nestedUmbrellaHeader, siblingHeaders: headers))
154+
diagnosticsEmitter.emit(.umbrellaHeaderParentDirHasSiblingHeaders(targetName: targetName, umbrellaHeader: nestedUmbrellaHeader, siblingHeaders: headers))
148155
return .none
149156
}
150157
return .umbrellaHeader(nestedUmbrellaHeader)
@@ -153,7 +160,7 @@ public struct ModuleMapGenerator {
153160
/// Check for the common mistake of naming the nested umbrella header 'TargetName.h' instead of 'ModuleName.h'.
154161
let misnamedNestedUmbrellaHeader = publicHeadersDir.appending(components: moduleName, targetName + ".h")
155162
if fileSystem.isFile(misnamedNestedUmbrellaHeader) {
156-
diagnostics.emit(.misnamedUmbrellaHeader(misnamedUmbrellaHeader: misnamedNestedUmbrellaHeader, umbrellaHeader: nestedUmbrellaHeader))
163+
diagnosticsEmitter.emit(.misnamedUmbrellaHeader(misnamedUmbrellaHeader: misnamedNestedUmbrellaHeader, umbrellaHeader: nestedUmbrellaHeader))
157164
}
158165

159166
// Otherwise, if 'PublicHeadersDir' contains only header files and no subdirectories, use it as the umbrella directory.
@@ -197,7 +204,6 @@ public enum GeneratedModuleMapType {
197204
case umbrellaDirectory(AbsolutePath)
198205
}
199206

200-
201207
public extension ModuleMapType {
202208
/// Returns the type of module map to generate for this kind of module map, or nil to not generate one at all.
203209
var generatedModuleMapType: GeneratedModuleMapType? {
@@ -209,36 +215,35 @@ public extension ModuleMapType {
209215
}
210216
}
211217

212-
213-
private extension Diagnostic.Message {
218+
private extension Basics.Diagnostic {
214219

215220
/// Warning emitted if the public-headers directory is missing.
216-
static func missingPublicHeadersDirectory(targetName: String, publicHeadersDir: AbsolutePath) -> Diagnostic.Message {
221+
static func missingPublicHeadersDirectory(targetName: String, publicHeadersDir: AbsolutePath) -> Self {
217222
.warning("no include directory found for target '\(targetName)'; libraries cannot be imported without public headers")
218223
}
219224

220225
/// Error emitted if the public-headers directory is inaccessible.
221-
static func inaccessiblePublicHeadersDirectory(targetName: String, publicHeadersDir: AbsolutePath, fileSystemError: Error) -> Diagnostic.Message {
226+
static func inaccessiblePublicHeadersDirectory(targetName: String, publicHeadersDir: AbsolutePath, fileSystemError: Error) -> Self {
222227
.error("cannot access public-headers directory for target '\(targetName)': \(String(describing: fileSystemError))")
223228
}
224229

225230
/// Warning emitted if a misnamed umbrella header was found.
226-
static func misnamedUmbrellaHeader(misnamedUmbrellaHeader: AbsolutePath, umbrellaHeader: AbsolutePath) -> Diagnostic.Message {
231+
static func misnamedUmbrellaHeader(misnamedUmbrellaHeader: AbsolutePath, umbrellaHeader: AbsolutePath) -> Self {
227232
.warning("\(misnamedUmbrellaHeader) should be renamed to \(umbrellaHeader) to be used as an umbrella header")
228233
}
229234

230235
/// Error emitted if there are directories next to a top-level umbrella header.
231-
static func umbrellaHeaderHasSiblingDirectories(targetName: String, umbrellaHeader: AbsolutePath, siblingDirs: Set<AbsolutePath>) -> Diagnostic.Message {
236+
static func umbrellaHeaderHasSiblingDirectories(targetName: String, umbrellaHeader: AbsolutePath, siblingDirs: Set<AbsolutePath>) -> Self {
232237
.error("target '\(targetName)' has invalid header layout: umbrella header found at '\(umbrellaHeader)', but directories exist next to it: \(siblingDirs.map({ String(describing: $0) }).sorted().joined(separator: ", ")); consider removing them")
233238
}
234239

235240
/// Error emitted if there are other directories next to the parent directory of a nested umbrella header.
236-
static func umbrellaHeaderParentDirHasSiblingDirectories(targetName: String, umbrellaHeader: AbsolutePath, siblingDirs: Set<AbsolutePath>) -> Diagnostic.Message {
241+
static func umbrellaHeaderParentDirHasSiblingDirectories(targetName: String, umbrellaHeader: AbsolutePath, siblingDirs: Set<AbsolutePath>) -> Self {
237242
.error("target '\(targetName)' has invalid header layout: umbrella header found at '\(umbrellaHeader)', but more than one directory exists next to its parent directory: \(siblingDirs.map({ String(describing: $0) }).sorted().joined(separator: ", ")); consider reducing them to one")
238243
}
239244

240245
/// Error emitted if there are other headers next to the parent directory of a nested umbrella header.
241-
static func umbrellaHeaderParentDirHasSiblingHeaders(targetName: String, umbrellaHeader: AbsolutePath, siblingHeaders: Set<AbsolutePath>) -> Diagnostic.Message {
246+
static func umbrellaHeaderParentDirHasSiblingHeaders(targetName: String, umbrellaHeader: AbsolutePath, siblingHeaders: Set<AbsolutePath>) -> Self {
242247
.error("target '\(targetName)' has invalid header layout: umbrella header found at '\(umbrellaHeader)', but additional header files exist: \((siblingHeaders.map({ String(describing: $0) }).sorted().joined(separator: ", "))); consider reducing them to one")
243248
}
244249
}

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ public final class PackageBuilder {
885885

886886
if fileSystem.exists(publicHeadersPath) {
887887
let moduleMapGenerator = ModuleMapGenerator(targetName: potentialModule.name, moduleName: potentialModule.name.spm_mangledToC99ExtendedIdentifier(), publicHeadersDir: publicHeadersPath, fileSystem: fileSystem)
888-
moduleMapType = moduleMapGenerator.determineModuleMapType(diagnostics: ObservabilitySystem.topScope.makeDiagnosticsEngine())
888+
moduleMapType = moduleMapGenerator.determineModuleMapType(observabilityScope: self.observabilityScope)
889889
} else if targetType == .library, manifest.toolsVersion >= .v5_5 {
890890
// If this clang target is a library, it must contain "include" directory.
891891
throw ModuleError.invalidPublicHeadersDirectory(potentialModule.name)

Tests/PackageLoadingTests/ModuleMapGenerationTests.swift

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,17 @@ class ModuleMapGeneration: XCTestCase {
9393
}
9494

9595
func testWarnings() throws {
96-
var fs = InMemoryFileSystem(emptyFiles:
97-
"/Foo.c")
96+
var fs = InMemoryFileSystem(emptyFiles: "/Foo.c")
9897
ModuleMapTester("Foo", in: fs) { result in
9998
result.checkNotCreated()
10099
result.checkDiagnostics { result in
101-
result.check(diagnostic: "no include directory found for target \'Foo\'; libraries cannot be imported without public headers", severity: .warning)
100+
var expectedMetadata = ObservabilityMetadata()
101+
expectedMetadata.targetName = "Foo"
102+
result.check(
103+
diagnostic: "no include directory found for target \'Foo\'; libraries cannot be imported without public headers",
104+
severity: .warning,
105+
metadata: expectedMetadata
106+
)
102107
}
103108
}
104109

@@ -114,21 +119,31 @@ class ModuleMapGeneration: XCTestCase {
114119
115120
""")
116121
result.checkDiagnostics { result in
117-
result.check(diagnostic: "/include/F-o-o.h should be renamed to /include/F_o_o.h to be used as an umbrella header", severity: .warning)
122+
var expectedMetadata = ObservabilityMetadata()
123+
expectedMetadata.targetName = "F-o-o"
124+
result.check(
125+
diagnostic: "/include/F-o-o.h should be renamed to /include/F_o_o.h to be used as an umbrella header",
126+
severity: .warning,
127+
metadata: expectedMetadata
128+
)
118129
}
119130
}
120131
}
121132

122133
func testUnsupportedLayouts() throws {
123-
var fs: InMemoryFileSystem
124-
125-
fs = InMemoryFileSystem(emptyFiles:
134+
var fs = InMemoryFileSystem(emptyFiles:
126135
"/include/Foo/Foo.h",
127136
"/include/Bar/Foo.h")
128137
ModuleMapTester("Foo", in: fs) { result in
129138
result.checkNotCreated()
130139
result.checkDiagnostics { result in
131-
result.check(diagnostic: "target 'Foo' has invalid header layout: umbrella header found at '/include/Foo/Foo.h', but more than one directory exists next to its parent directory: /include/Bar; consider reducing them to one", severity: .error)
140+
var expectedMetadata = ObservabilityMetadata()
141+
expectedMetadata.targetName = "Foo"
142+
result.check(
143+
diagnostic: "target 'Foo' has invalid header layout: umbrella header found at '/include/Foo/Foo.h', but more than one directory exists next to its parent directory: /include/Bar; consider reducing them to one",
144+
severity: .error,
145+
metadata: expectedMetadata
146+
)
132147
}
133148
}
134149

@@ -138,7 +153,13 @@ class ModuleMapGeneration: XCTestCase {
138153
ModuleMapTester("Foo", in: fs) { result in
139154
result.checkNotCreated()
140155
result.checkDiagnostics { result in
141-
result.check(diagnostic: "target 'Foo' has invalid header layout: umbrella header found at '/include/Foo.h', but directories exist next to it: /include/Bar; consider removing them", severity: .error)
156+
var expectedMetadata = ObservabilityMetadata()
157+
expectedMetadata.targetName = "Foo"
158+
result.check(
159+
diagnostic: "target 'Foo' has invalid header layout: umbrella header found at '/include/Foo.h', but directories exist next to it: /include/Bar; consider removing them",
160+
severity: .error,
161+
metadata: expectedMetadata
162+
)
142163
}
143164
}
144165
}
@@ -149,7 +170,7 @@ func ModuleMapTester(_ targetName: String, includeDir: String = "include", in fi
149170
let observability = ObservabilitySystem.bootstrapForTesting()
150171
// Create a module map generator, and determine the type of module map to use for the header directory. This may emit diagnostics.
151172
let moduleMapGenerator = ModuleMapGenerator(targetName: targetName, moduleName: targetName.spm_mangledToC99ExtendedIdentifier(), publicHeadersDir: AbsolutePath.root.appending(component: includeDir), fileSystem: fileSystem)
152-
let moduleMapType = moduleMapGenerator.determineModuleMapType(diagnostics: ObservabilitySystem.topScope.makeDiagnosticsEngine())
173+
let moduleMapType = moduleMapGenerator.determineModuleMapType(observabilityScope: ObservabilitySystem.topScope)
153174

154175
// Generate a module map and capture any emitted diagnostics.
155176
let generatedModuleMapPath = AbsolutePath.root.appending(components: "module.modulemap")

0 commit comments

Comments
 (0)