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:
parent
0e21b86781
commit
cadca9621c
@ -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`.
|
||||
|
||||
@ -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):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user