PureXML/scripts/check-forbidden-patterns.sh
Mihaela Mihaljevic 708390242c chore: scaffold PureXML pure-Swift XML package
Root Swift package mirroring PureYAML's structure, rules, and verification
gates. Includes the XML node model (Node, Element, Attribute, QualifiedName),
a working emitter (Serializer) with escaping and pretty/compact options, and
structural validation. The parser surface is stable; parse() raises
notImplemented until the scanner lands, pinned by a test.

- dependency-free, namespaced under PureXML
- portability and style gates carried over (style, namespacing, forbidden
  patterns, swiftformat, swiftlint, linux, wasm, windows CI)
- 11 tests passing
2026-06-07 23:20:20 +02:00

92 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Repo contract gate for PureXML "never" rules.
#
# These checks cover patterns that Swift unit tests cannot see reliably:
# package dependencies, source imports, C/generated parser files, XCTest-style
# tests, platform branches, and singleton/service-locator wiring.
set -u
FAIL=0
fail() {
echo "forbidden-patterns: $1" >&2
FAIL=1
}
report_matches() {
message="$1"
matches="$2"
if [ -n "$matches" ]; then
fail "$message"
printf '%s\n' "$matches" | sed 's/^/ /' >&2
fi
}
if ! grep -qE '^[[:space:]]*dependencies:[[:space:]]*\[[[:space:]]*\],[[:space:]]*$' Package.swift; then
fail "Package.swift must keep dependencies: []"
fi
package_forbidden=$(
grep -nE '\.package[[:space:]]*\(|\.binaryTarget[[:space:]]*\(|\.systemLibrary[[:space:]]*\(' Package.swift 2>/dev/null || true
)
report_matches "Package.swift must not declare external, binary, or system-library targets" "$package_forbidden"
source_imports=$(
grep -RInE '^[[:space:]]*import[[:space:]]+[A-Za-z_][A-Za-z0-9_]*' Sources --include '*.swift' 2>/dev/null || true
)
report_matches "Sources must stay standard-library-only and import no modules" "$source_imports"
source_platform_branches=$(
grep -RInE '^[[:space:]]*#if[[:space:]]+(os|canImport)[[:space:]]*\(' Sources --include '*.swift' 2>/dev/null || true
)
report_matches "Sources must not add platform-specific branches without an explicit rule change" "$source_platform_branches"
source_runtimes=$(
find Sources -type f \( \
-name '*.c' -o \
-name '*.cc' -o \
-name '*.cpp' -o \
-name '*.h' -o \
-name '*.hpp' -o \
-name '*.m' -o \
-name '*.mm' -o \
-name '*.js' -o \
-name '*.ts' -o \
-name '*.wasm' -o \
-name '*.y' -o \
-name '*.l' -o \
-name '*.g4' \
\) -print 2>/dev/null
)
report_matches "Sources must not contain C, JavaScript, WebAssembly blobs, or generated parser runtime files" "$source_runtimes"
source_singletons=$(
grep -RInE 'static[[:space:]]+(let|var)[[:space:]]+shared\b|^[[:space:]]*(public[[:space:]]+)?(final[[:space:]]+)?(class|struct|enum)[[:space:]]+ServiceLocator\b|[A-Za-z0-9_]*(Resolver|Container|Environment)[[:space:]]*\.[[:space:]]*shared\b' Sources --include '*.swift' 2>/dev/null || true
)
report_matches "Sources must not introduce singleton or service-locator access patterns" "$source_singletons"
source_traps=$(
grep -RInE '\bfatalError[[:space:]]*\(|\bpreconditionFailure[[:space:]]*\(|\bassertionFailure[[:space:]]*\(|\btry!|\bas!|[A-Za-z0-9_)\]}][[:space:]]*![[:space:]]*([).,\];:]|$)' Sources --include '*.swift' 2>/dev/null || true
)
report_matches "Sources must not use traps, forced casts, try!, or force unwraps" "$source_traps"
test_imports=$(
grep -RInE '^[[:space:]]*(@testable[[:space:]]+)?import[[:space:]]+[A-Za-z_][A-Za-z0-9_]*' Tests --include '*.swift' 2>/dev/null \
| grep -vE '^[^:]+:[0-9]+:[[:space:]]*@testable[[:space:]]+import[[:space:]]+PureXML[[:space:]]*$' \
| grep -vE '^[^:]+:[0-9]+:[[:space:]]*import[[:space:]]+Foundation[[:space:]]*$' \
| grep -vE '^[^:]+:[0-9]+:[[:space:]]*import[[:space:]]+Testing[[:space:]]*$' || true
)
report_matches "Tests may import only Foundation, Testing, and @testable PureXML" "$test_imports"
test_xctest=$(
grep -RInE '\bXCTest(Case|Expectation)?\b|\bXCTAssert[A-Za-z]*\b|^[[:space:]]*import[[:space:]]+XCTest[[:space:]]*$' Tests --include '*.swift' 2>/dev/null || true
)
report_matches "Tests must stay on Swift Testing and avoid XCTest-style APIs" "$test_xctest"
if [ "$FAIL" -eq 0 ]; then
echo "forbidden-patterns: OK"
fi
exit "$FAIL"