Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/code-style.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: code-style

# Rollout of the ecosystem's code-style policy (SwiftDXF#13); see
# docs/code-style-policy-proposal-2026-08.md in the `ecosystem` repo for the
# full rationale, and OCCTSwiftScripts#114/#115 for the reference
# implementation this repo follows. Full sweep, not a gradual rollout: this
# repo is small enough (~1,125 Swift lines, 6 files) to fully sweep into
# compliance in one PR and go straight to a blocking gate, rather than
# needing OCCTSwift's gradual "if you touch it, you fix it" exemption
# manifest.
#
# Pure text analysis (formatting + lint), no compiled output needed by any of
# the three checks, so this stays a macOS runner only because that's where
# swift-format and swiftlint are both readily available via Homebrew.
#
# swift-format and SwiftLint are blocking: formatting has no judgment call in
# it. The comment-ratio check is report-only by design (see the script's own
# header) and is not a gate; it always exits 0.

on:
push:
paths:
- 'Sources/**'
- 'Tests/**'
- '.swift-format'
- '.swiftlint.yml'
- 'Scripts/comment-ratio-check.sh'
- '.github/workflows/code-style.yml'
pull_request:
paths:
- 'Sources/**'
- 'Tests/**'
- '.swift-format'
- '.swiftlint.yml'
- 'Scripts/comment-ratio-check.sh'
- '.github/workflows/code-style.yml'
workflow_dispatch:

jobs:
code-style:
runs-on: macos-15
steps:
- uses: actions/checkout@v4

- name: Install swift-format and SwiftLint
run: brew install swift-format swiftlint

- name: swift-format lint --strict
run: |
find Sources Tests -name '*.swift' -print0 \
| xargs -0 swift-format lint --strict --configuration .swift-format

- name: swiftlint lint --strict
run: swiftlint lint --strict --config .swiftlint.yml

- name: Comment:code ratio (report-only, never fails)
run: Scripts/comment-ratio-check.sh
75 changes: 75 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"version" : 1,
"lineLength" : 100,
"indentation" : {
"spaces" : 4
},
"tabWidth" : 4,
"maximumBlankLines" : 1,
"respectsExistingLineBreaks" : true,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : false,
"lineBreakBeforeEachGenericRequirement" : false,
"lineBreakBetweenDeclarationAttributes" : false,
"multiElementCollectionTrailingCommas" : true,
"prioritizeKeepingFunctionOutputTogether" : false,
"reflowMultilineStringLiterals" : "never",
"spacesAroundRangeFormationOperators" : false,
"spacesBeforeEndOfLineComments" : 2,
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"orderedImports" : {
"includeConditionalImports" : false
},
"noAssignmentInExpressions" : {
"allowedFunctions" : [
"XCTAssertNoThrow"
]
},
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLiteralForEmptyCollectionInit" : false,
"AlwaysUseLowerCamelCase" : true,
"AmbiguousTrailingClosureOverload" : true,
"AvoidRetroactiveConformances" : true,
"BeginDocumentationCommentWithOneLineSummary" : true,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoAssignmentInExpressions" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyLinesOpeningClosingBraces" : false,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : false,
"NoParensAroundConditions" : true,
"NoPlaygroundLiterals" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OmitExplicitReturns" : false,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : true,
"OrderedImports" : true,
"ReplaceForEachWithForLoop" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"TypeNamesShouldBeCapitalized" : true,
"UseEarlyExits" : false,
"UseExplicitNilCheckInConditions" : true,
"UseLetInEveryBoundCaseVariable" : true,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : true,
"UseSynthesizedInitializer" : true,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : true
}
}
24 changes: 24 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Deliberately narrow: `only_rules`, not `disabled_rules`. SwiftLint's default
# rule set covers two kinds of territory this repo doesn't want it opining on:
#
# - Layout (colon/comma/opening_brace/line_length/...): swift-format already
# owns this; running both fights, since they can disagree on the same line.
# - Code-quality/complexity (identifier_name, cyclomatic_complexity,
# function_body_length, nesting, type_body_length, file_length, ...), a
# separate concern from code style, and one that overlaps the ecosystem's
# own code-structure policy (a repo that needs a structural pass runs one
# as its own scoped initiative, not as a side effect of a style-lint gate).
#
# What's left is the one rule that catches something swift-format has no
# equivalent for: a doc comment not attached to any declaration.
#
# See docs/code-style-policy-proposal-2026-08.md in the ecosystem repo for
# the full rationale. Pattern matches OCCTSwiftScripts's own .swiftlint.yml,
# the reference implementation for this policy (OCCTSwiftScripts#115).

only_rules:
- orphaned_doc_comment

excluded:
- .build
- Tests
57 changes: 57 additions & 0 deletions Scripts/comment-ratio-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# comment-ratio-check.sh: flag Swift files where comment lines outnumber code
# lines, as a signal for a human to look, not a fail.
#
# Part of the ecosystem's code-style policy rollout (SwiftDXF#13); see
# docs/code-style-policy-proposal-2026-08.md in the `ecosystem` repo for the
# full rationale, and OCCTSwiftScripts#114/#115 for the reference
# implementation this script is copied from. A high ratio is sometimes
# legitimate (a small function with several real caveats worth spelling out)
# and sometimes means a doc comment has drifted into restating design
# rationale that belongs in docs/ instead: this script surfaces the number,
# it doesn't judge which case it is. Report-only: always exits 0, since
# failing every file above a threshold on day one, in a codebase nobody has
# swept yet, punishes the report instead of the problem.
#
# Usage:
# Scripts/comment-ratio-check.sh # default threshold: 1.0
# Scripts/comment-ratio-check.sh 1.5 # custom threshold
set -euo pipefail

threshold="${1:-1.0}"

[ -d Sources ] || { echo "FAIL: Sources/ not found; run from the repo root" >&2; exit 1; }

flagged=0

while IFS= read -r -d '' file; do
comment=0
code=0
while IFS= read -r line; do
trimmed="${line#"${line%%[![:space:]]*}"}"
[ -z "$trimmed" ] && continue
case "$trimmed" in
//*) comment=$((comment + 1)) ;;
*) code=$((code + 1)) ;;
esac
done < "$file"

[ "$code" -eq 0 ] && continue

# POSIX sh has no float math; compare as comment*100 >= threshold*code so
# a fractional threshold (the common case: 1.0, 1.5) still works exactly.
threshold_x100=$(awk -v t="$threshold" 'BEGIN { printf "%d", t * 100 }')
if [ $((comment * 100)) -ge $((threshold_x100 * code)) ]; then
ratio=$(awk -v c="$comment" -v d="$code" 'BEGIN { printf "%.2f", c / d }')
printf ' %-55s comment=%-5d code=%-5d ratio=%s\n' "$file" "$comment" "$code" "$ratio"
flagged=$((flagged + 1))
fi
done < <(find Sources -name '*.swift' -print0 | sort -z)

if [ "$flagged" -eq 0 ]; then
echo "comment-ratio-check: no files at or above ${threshold}x comment:code (Sources/)"
else
echo "comment-ratio-check: $flagged file(s) at or above ${threshold}x comment:code (Sources/): not a failure, a signal to look"
fi

exit 0
Loading
Loading