92 lines
3.5 KiB
Bash
92 lines
3.5 KiB
Bash
#!/usr/bin/env bash
|
|
# Repo contract gate for PureYAML "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:]]+PureYAML[[: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 PureYAML" "$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"
|