in Generator/Sources/NeedleFramework/Parsing/Pluginized/Processors/PluginExtensionCycleValidator.swift [39:69]
func process() throws {
for component in pluginizedComponents {
guard let pluginExtension = component.pluginExtension else {
throw GenericError.withMessage("\(component.data.name)'s plugin extension has not been linked.")
}
guard let nonCoreDependency = component.nonCoreComponent?.dependencyProtocol else {
throw GenericError.withMessage("\(component.data.name)'s non-core component dependency has not been linked.")
}
let nonCoreDepProperties = Set<Property>(nonCoreDependency.properties)
let pluginExtensionProperties = Set<Property>(pluginExtension.properties)
let componentProperties = Set<Property>(component.data.properties)
// This isn't an exact cycle matching, since we cannot check for
// how the property is provided by the core component. This just
// checks that core component provides a property which is also
// required by the plugin extension and the non-core component dependency.
// SourceKit does not provide the last bit of information, where the
// core component provides the property via `pluginExtension.property`.
// In this case, we are assuming the property is provided via the
// plugin extension, since it lists it, therefore causing a cycle.
let intersections = nonCoreDepProperties.intersection(pluginExtensionProperties).intersection(componentProperties)
if !intersections.isEmpty {
let cyclicPropertiesString = intersections
.map { (property: Property) -> String in
return "(\(property.name): \(property.type))"
}
.joined(separator: ", ")
throw GenericError.withMessage("\(component.data.name) contains cyclic plugin extension properties \(cyclicPropertiesString).")
}
}
}