refactor(xslt): remove dead namespace-fixup helpers (#318)

XSLTNamespaceFixup.fixAttributeName and resolvedPrefix had zero callers.
The result-tree attribute fixup was inlined into fix(_ element:) and
evolved past them (the inlined path also shadows a carried prefix via
localPrefixes, which the helpers lacked), so the helpers were dead,
diverged duplicates. No behavior change; build green, 1759 tests pass.
This commit is contained in:
Mihaela Mihaljevic 2026-06-26 08:17:39 +02:00 committed by GitHub
parent 0e21b86781
commit cadca9621c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 2 additions and 48 deletions

View File

@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Five unused internal schema-consistency wrappers (`idAttributeErrors`, `consistencyErrors`, `postNamedTypeErrors`, `structureErrors`, `includeCompositionErrors`) that returned `[String]` reason lists, along with the now-orphaned `postCompileErrors(schema:context:containers:namedTypes:)` overload and the `SchemaCompileNamedTypes` struct it consumed. None had callers; the `XSDParser.consistencyErrors` overload was shadowed by the distinct, still-live `Validation.XSDSchema.consistencyErrors` (a different signature returning `ValidationError`), which is why a name-only search first read it as used. The located-diagnostic API (the `*Findings` functions returning `SchemaLocatedFinding`, and `Validation.XSDSchema` returning `ValidationError`) superseded all of them. Removing them deletes dead code with no behavior change; the live `*Findings` and `Validation.XSDSchema` functions are unchanged. A stale doc-comment reference to the renamed `userTypeValueConstraintErrors` (now `userTypeValueConstraintFindings`) was corrected at the same time.
- Two unused private helpers in `XSLTNamespaceFixup` (`fixAttributeName` and `resolvedPrefix`). The result-tree attribute fixup they implemented was inlined into `fix(_ element:)` and evolved past them (the inlined version additionally shadows a carried prefix through `localPrefixes`, which the helpers did not), leaving both with zero callers. Removing them deletes dead, diverged duplicate logic with no behavior change; the live inlined path is unchanged.
### Fixed
- `xpointer(string-range(...))` no longer uses a quadratic substring search. It matched the search string at every position of each node's value and re-allocated the whole needle-width window per position (O(text * needle), a denial-of-service vector on a long node value with a near-matching needle); it now uses a linear-time Knuth-Morris-Pratt search with the failure function built once. The matches are unchanged: same non-overlapping, left-to-right occurrences, same offset/length. A near-matching needle over a 16000-character node drops from about 0.18 s to about 0.002 s (~100x), and the cost is now linear. Guarded by the new non-overlapping and backtracking cases in `XPointerRangeTests`.

View File

@ -34,54 +34,6 @@ enum XSLTNamespaceFixup {
}
}
/// A namespaced attribute needs a prefix bound to its URI, generated
/// fresh when absent or taken by a different binding.
private static func fixAttributeName(at index: Int, attributes: inout [PureXML.Model.Attribute], scope: inout [String: String], counter: inout Int) {
let attributeName = attributes[index].name
guard let uri = attributeName.namespaceURI, !uri.isEmpty,
attributeName.prefix != "xmlns", attributeName.prefix != "xml"
else { return }
var prefix = attributeName.prefix
if let candidate = prefix, scope[candidate] == uri {
return // Already bound correctly.
}
if prefix == nil || scope[prefix ?? ""] != nil {
if let existing = scope.first(where: { $0.value == uri && !$0.key.isEmpty })?.key {
prefix = existing
} else {
while scope["ns\(counter)"] != nil {
counter += 1
}
prefix = "ns\(counter)"
counter += 1
}
}
guard let resolved = prefix else { return }
if scope[resolved] != uri {
scope[resolved] = uri
attributes.append(.init("xmlns:\(resolved)", uri))
}
attributes[index] = .init(
name: .init(prefix: resolved, localName: attributeName.localName, namespaceURI: uri),
value: attributes[index].value,
)
}
/// A prefix bound to `uri`: the carried one when free, an existing
/// binding for the same URI, or a fresh `ns<n>`.
private static func resolvedPrefix(for uri: String, carried: String?, scope: [String: String], counter: inout Int) -> String {
if let carried, scope[carried] == nil { return carried }
if let existing = scope.first(where: { $0.value == uri && !$0.key.isEmpty })?.key {
return existing
}
var fresh = counter
while scope["ns\(fresh)"] != nil {
fresh += 1
}
counter = fresh + 1
return "ns\(fresh)"
}
private static func fix(_ node: PureXML.Model.Node, inScope: [String: String], counter: inout Int) -> PureXML.Model.Node {
switch node {
case let .document(children):