Sidestep `SourceKitten`'s off-by-one bug when parsing generic parameter inheritance.

This commit is contained in:
Matyáš Kříž 2020-06-28 16:45:16 +02:00
parent e2bb73412f
commit a0a7c82526
2 changed files with 38 additions and 4 deletions

View File

@ -99,6 +99,9 @@ public struct Tokenizer {
let children = subtokens.noneOf(Initializer.self)
let genericParameters = subtokens.only(GenericParameter.self)
// FIXME: Remove when SourceKitten fixes the off-by-one error that includes the ending `>` in the last inherited type.
let fixedGenericParameters = fixSourceKittenLastGenericParameterBug(genericParameters)
return ProtocolDeclaration(
name: name,
accessibility: accessibility,
@ -109,7 +112,7 @@ public struct Tokenizer {
children: children,
inheritedTypes: tokenizedInheritedTypes,
attributes: attributes,
genericParameters: genericParameters)
genericParameters: fixedGenericParameters)
case Kinds.ClassDeclaration.rawValue:
let subtokens = tokenize(dictionary[Key.Substructure.rawValue] as? [SourceKitRepresentable] ?? [])
@ -124,6 +127,9 @@ public struct Tokenizer {
}
let genericParameters = subtokens.only(GenericParameter.self)
// FIXME: Remove when SourceKitten fixes the off-by-one error that includes the ending `>` in the last inherited type.
let fixedGenericParameters = fixSourceKittenLastGenericParameterBug(genericParameters)
return ClassDeclaration(
name: name,
accessibility: accessibility,
@ -134,7 +140,7 @@ public struct Tokenizer {
children: children,
inheritedTypes: tokenizedInheritedTypes,
attributes: attributes,
genericParameters: genericParameters)
genericParameters: fixedGenericParameters)
case Kinds.ExtensionDeclaration.rawValue:
return ExtensionDeclaration(range: range!)
@ -185,6 +191,9 @@ public struct Tokenizer {
}
}
// FIXME: Remove when SourceKitten fixes the off-by-one error that includes the ending `>` in the last inherited type.
let fixedGenericParameters = fixSourceKittenLastGenericParameterBug(genericParameters)
// When bodyRange != nil, we need to create `ClassMethod` instead of `ProtocolMethod`
if let bodyRange = bodyRange {
return ClassMethod(
@ -196,7 +205,7 @@ public struct Tokenizer {
parameters: namedParameters,
bodyRange: bodyRange,
attributes: attributes,
genericParameters: genericParameters)
genericParameters: fixedGenericParameters)
} else {
return ProtocolMethod(
name: name,
@ -206,7 +215,7 @@ public struct Tokenizer {
nameRange: nameRange!,
parameters: namedParameters,
attributes: attributes,
genericParameters: genericParameters)
genericParameters: fixedGenericParameters)
}
case Kinds.GenericParameter.rawValue:
@ -292,6 +301,7 @@ public struct Tokenizer {
let inheritedTypeElement = (dictionary[Key.InheritedTypes.rawValue] as? [SourceKitRepresentable] ?? []).first
let inheritedType = (inheritedTypeElement as? [String: SourceKitRepresentable] ?? [:])[Key.Name.rawValue] as? String
let inheritanceDeclaration: InheritanceDeclaration?
if let inheritedType = inheritedType {
inheritanceDeclaration = .init(name: inheritedType)
} else {
@ -468,6 +478,26 @@ public struct Tokenizer {
return ReturnSignature(throwString: throwString, returnType: returnType ?? WrappableType.type("Void"), whereConstraints: whereConstraints)
}
// FIXME: Remove when SourceKitten fixes the off-by-one error that includes the ending `>` in the last inherited type.
private func fixSourceKittenLastGenericParameterBug(_ genericParameters: [GenericParameter]) -> [GenericParameter] {
let fixedGenericParameters: [GenericParameter]
if let lastGenericParameter = genericParameters.last,
let inheritedType = lastGenericParameter.inheritedType,
inheritedType.name.hasSuffix(">>") == true {
fixedGenericParameters = genericParameters.dropLast() + [
GenericParameter(
name: lastGenericParameter.name,
range: lastGenericParameter.range.lowerBound..<lastGenericParameter.range.upperBound - 1,
inheritedType: InheritanceDeclaration(name: String(inheritedType.name.dropLast()))
)
]
} else {
fixedGenericParameters = genericParameters
}
return fixedGenericParameters
}
}
extension String {

View File

@ -22,6 +22,10 @@ class GenericClass<T: CustomStringConvertible, U: Codable & CustomStringConverti
readWritePropertyV = theV
}
func genericMethodParameter<G: GenericClass<T, U, V>>(g: G) {}
func genericMethodParameterNested<G: GenericClass<T, [Int], Array<String>>>(g: G) {}
func genericWhereMethodParameter<G>(g: G) where G: GenericClass<T, [Int], V> {}
func genericWhereMethodParameterNested<G>(g: G) where G: GenericClass<T, U, Array<String>> {}