Skip to content

Commit 5b50d3f

Browse files
restructure ToolsVersionLoader.Error.ToolsVersionSpecificationMalformationLocation to extract (or distribute?) common errors from different locations
1 parent a50f997 commit 5b50d3f

File tree

3 files changed

+63
-69
lines changed

3 files changed

+63
-69
lines changed

Sources/Commands/SwiftPackageTool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ extension SwiftPackageTool {
489489
case .set(let value):
490490
guard let toolsVersion = ToolsVersion(string: value) else {
491491
// FIXME: Probably lift this error defination to ToolsVersion.
492-
throw ToolsVersionLoader.Error.malformedToolsVersionSpecification(.versionSpecifier(value))
492+
throw ToolsVersionLoader.Error.malformedToolsVersionSpecification(.versionSpecifier(.isMisspelt(value)))
493493
}
494494
try writeToolsVersion(at: pkg, version: toolsVersion, fs: localFileSystem)
495495

Sources/PackageLoading/ToolsVersionLoader.swift

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -108,38 +108,23 @@ public class ToolsVersionLoader: ToolsVersionLoaderProtocol {
108108
// FIXME: Use generic associated type `T: StringProtocol` instead of concrete types `String` and `Substring`, when/if this feature comes to Swift.
109109
public enum Error: Swift.Error, CustomStringConvertible {
110110

111-
// FIXME: Separate the "missing"-prefixed cases into a different enum.
112-
// Or, generalise the non-"missing"-prefixed cases. E.g.
113-
//
114-
// public enum ToolsVersionSpecificationMalformation {
115-
// public enum Details {
116-
// case isMissing
117-
// case isMisspelt(_ misspelling: Substring) // Might need to repl
118-
// }
119-
// case commentMarker(_ malformationDetails: Details)
120-
// case label(_ malformationDetails: Details)
121-
// case versionSpecifier(_ malformationDetails: Details)
122-
// }
123-
//
124-
// throw Error.malformedToolsVersionSpecification(.commentMarker(.isMissing))
125-
// throw Error.malformedToolsVersionSpecification(.label(.isMisspelt(parsedLabel)))
126-
//
127-
/// Details of the tools version specification's malformation.
128-
public enum ToolsVersionSpecificationMalformation {
129-
/// The comment marker of the Swift tools version specification is missing.
130-
///
131-
/// Sometimes the missing comment marker is an indication that the entire Swift tools version specification is missing.
132-
case missingCommentMarker
133-
/// The label part of the Swift tools version specification is missing.
134-
case missingLabel
135-
/// The version specifier is missing.
136-
case missingVersionSpecifier
111+
/// Location of the tools version specification's malformation.
112+
public enum ToolsVersionSpecificationMalformationLocation {
113+
/// The nature of malformation at the location in Swift tools version specification.
114+
public enum MalformationDetails {
115+
/// The Swift tools version specification component is missing.
116+
case isMissing
117+
/// The Swift tools version specification component is misspelt.
118+
case isMisspelt(_ misspelling: String)
119+
}
137120
/// The comment marker is malformed.
138-
case commentMarker(_ commentMarker: String)
121+
///
122+
/// If the comment marker is missing, it could be an indication that the entire Swift tools version specification is missing.
123+
case commentMarker(_ malformationDetails: MalformationDetails)
139124
/// The label part of the Swift tools version specification is malformed.
140-
case label(_ label: String)
125+
case label(_ malformationDetails: MalformationDetails)
141126
/// The version specifier is malformed.
142-
case versionSpecifier(_ versionSpecifier: String)
127+
case versionSpecifier(_ malformationDetails: MalformationDetails)
143128
}
144129

145130
/// Details of backward-incompatible contents with Swift tools version ≤ 5.3.
@@ -159,7 +144,7 @@ public class ToolsVersionLoader: ToolsVersionLoaderProtocol {
159144
/// Package manifest file's content can not be decoded as a UTF-8 string.
160145
case nonUTF8EncodedManifest(path: AbsolutePath)
161146
/// Malformed tools version specification.
162-
case malformedToolsVersionSpecification(_ malformation: ToolsVersionSpecificationMalformation)
147+
case malformedToolsVersionSpecification(_ malformationLocation: ToolsVersionSpecificationMalformationLocation)
163148
/// Backward-incompatible contents with Swift tools version ≤ 5.3.
164149
case backwardIncompatiblePre5_3_1(_ incompatibility: BackwardIncompatibilityPre5_3_1, specifiedVersion: ToolsVersion)
165150

@@ -191,21 +176,30 @@ public class ToolsVersionLoader: ToolsVersionLoaderProtocol {
191176
return "the package manifest at '\(manifestFilePath)' cannot be accessed (\(reason))"
192177
case let .nonUTF8EncodedManifest(manifestFilePath):
193178
return "the package manifest at '\(manifestFilePath)' cannot be decoded using UTF-8"
194-
case let .malformedToolsVersionSpecification(malformation):
195-
switch malformation {
196-
case .missingCommentMarker:
197-
return "the manifest is missing a Swift tools version specification; consider prepending to the manifest '// swift-tools-version:\(ToolsVersion.currentToolsVersion)' to specify the current Swift toolchain version as the lowest supported version by the project; if such a specification already exists, consider moving it to the top of the manifest, or prepending it with '//' to help Swift Package Manager find it"
198-
case .missingLabel:
199-
return "the Swift tools version specification is missing a label; consider inserting 'swift-tools-version:' between the comment marker and the version specifier"
200-
case .missingVersionSpecifier:
201-
// If the version specifier is missing, then its terminator must be missing as well. So, there is nothing in between the version specifier and everything that should be in front the version specifier. So, appending a valid version specifier will fix this error.
202-
return "the Swift tools version specification is missing a version specifier; consider appending '\(ToolsVersion.currentToolsVersion)' to the line to specify the current Swift toolchain version as the lowest supported version by the project"
203-
case let .commentMarker(commentMarker):
204-
return "the comment marker '\(commentMarker)' is malformed for the Swift tools version specification; consider replacing it with '//'"
205-
case let .label(label):
206-
return "the Swift tools version specification's label '\(label)' is malformed; consider replacing it with 'swift-tools-version:'"
207-
case let .versionSpecifier(versionSpecifier):
208-
return "the Swift tools version '\(versionSpecifier)' is not valid; consider replacing it with '\(ToolsVersion.currentToolsVersion)' to specify the current Swift toolchain version as the lowest supported version by the project"
179+
case let .malformedToolsVersionSpecification(malformationLocation):
180+
switch malformationLocation {
181+
case .commentMarker(let malformationDetails):
182+
switch malformationDetails {
183+
case .isMissing:
184+
return "the manifest is missing a Swift tools version specification; consider prepending to the manifest '// swift-tools-version:\(ToolsVersion.currentToolsVersion)' to specify the current Swift toolchain version as the lowest supported version by the project; if such a specification already exists, consider moving it to the top of the manifest, or prepending it with '//' to help Swift Package Manager find it"
185+
case .isMisspelt(let misspeltCommentMarker):
186+
return "the comment marker '\(misspeltCommentMarker)' is misspelt for the Swift tools version specification; consider replacing it with '//'"
187+
}
188+
case .label(let malformationDetails):
189+
switch malformationDetails {
190+
case .isMissing:
191+
return "the Swift tools version specification is missing a label; consider inserting 'swift-tools-version:' between the comment marker and the version specifier"
192+
case .isMisspelt(let misspeltLabel):
193+
return "the Swift tools version specification's label '\(misspeltLabel)' is misspelt; consider replacing it with 'swift-tools-version:'"
194+
}
195+
case .versionSpecifier(let malformationDetails):
196+
switch malformationDetails {
197+
case .isMissing:
198+
// If the version specifier is missing, then its terminator must be missing as well. So, there is nothing in between the version specifier and everything that should be in front the version specifier. So, appending a valid version specifier will fix this error.
199+
return "the Swift tools version specification is missing a version specifier; consider appending '\(ToolsVersion.currentToolsVersion)' to the line to specify the current Swift toolchain version as the lowest supported version by the project"
200+
case .isMisspelt(let misspeltVersionSpecifier):
201+
return "the Swift tools version '\(misspeltVersionSpecifier)' is misspelt or otherwise invalid; consider replacing it with '\(ToolsVersion.currentToolsVersion)' to specify the current Swift toolchain version as the lowest supported version by the project"
202+
}
209203
}
210204
// FIXME: The error messages probably can be more concise, while still hitting all the key points.
211205
case let .backwardIncompatiblePre5_3_1(incompatibility, specifiedVersion):
@@ -324,26 +318,26 @@ public class ToolsVersionLoader: ToolsVersionLoaderProtocol {
324318

325319
let commentMarker = toolsVersionSpecificationComponents.commentMarker
326320
guard !commentMarker.isEmpty else {
327-
throw Error.malformedToolsVersionSpecification(.missingCommentMarker)
321+
throw Error.malformedToolsVersionSpecification(.commentMarker(.isMissing))
328322
}
329323

330324
let label = toolsVersionSpecificationComponents.label
331325
guard !label.isEmpty else {
332-
throw Error.malformedToolsVersionSpecification(.missingLabel)
326+
throw Error.malformedToolsVersionSpecification(.label(.isMissing))
333327
}
334328

335329
let versionSpecifier = toolsVersionSpecificationComponents.versionSpecifier
336330
guard !versionSpecifier.isEmpty else {
337-
throw Error.malformedToolsVersionSpecification(.missingVersionSpecifier)
331+
throw Error.malformedToolsVersionSpecification(.versionSpecifier(.isMissing))
338332
}
339333

340334
guard toolsVersionSpecificationComponents.everythingUpToVersionSpecifierIsWellFormed else {
341335
if commentMarker != "//" {
342-
throw Error.malformedToolsVersionSpecification(.commentMarker(String(commentMarker)))
336+
throw Error.malformedToolsVersionSpecification(.commentMarker(.isMisspelt(String(commentMarker))))
343337
}
344338

345339
if label.lowercased() != "swift-tools-version:" {
346-
throw Error.malformedToolsVersionSpecification(.label(String(label)))
340+
throw Error.malformedToolsVersionSpecification(.label(.isMisspelt(String(label))))
347341
}
348342

349343
// The above If-statements should have covered all possible malformations in Swift tools version specification up to the version specifier.
@@ -352,7 +346,7 @@ public class ToolsVersionLoader: ToolsVersionLoaderProtocol {
352346
}
353347

354348
guard let version = ToolsVersion(string: String(versionSpecifier)) else {
355-
throw Error.malformedToolsVersionSpecification(.versionSpecifier(String(versionSpecifier)))
349+
throw Error.malformedToolsVersionSpecification(.versionSpecifier(.isMisspelt(String(versionSpecifier))))
356350
}
357351

358352
guard version > .v5_3 || manifestComponents.isCompatibleWithPreSwift5_3_1 else {

0 commit comments

Comments
 (0)