feat: Add inline suppression for LCOM4 class cohesion#39
Merged
Conversation
Extend // swift-complexity:disable to type declarations (class/struct/actor) so a reviewed low-cohesion type can be exempted from LCOM4 judgments without excluding its whole file via --exclude, which would also hide the file's complexity violations. Closes #36. Design: - SuppressionParser now takes an applicableTo scope and intersects the parsed metrics with it: FunctionDetector passes SuppressedMetric.functionLevel (cyclomatic/cognitive), NominalTypeDetector passes SuppressedMetric.typeLevel (lcom4). A bare disable therefore means "every metric of this declaration itself" - a bare disable above a type suppresses only lcom4 and never cascades to member functions, and naming a metric of the wrong level (lcom4 above a function, cyclomatic above a class) suppresses nothing, keeping the fail-closed contract. - The intersection also preserves the v1.1.0 JSON output: without it, adding the lcom4 case to SuppressedMetric.allCases would have leaked "lcom4" into the suppressedMetrics array of bare-disabled functions. - ClassCohesion gains an optional suppressedMetrics set mirroring FunctionComplexity; the LCOM4 value is still computed and shown in every output format, only the judgments are skipped. All three cohesion judgment sites are gated: the Xcode diagnostic, SARIF's lcom4_cohesion results, and the CLI's threshold filtering. The exit code needs no change because LCOM4 never influenced it. - --report-suppressions now also lists suppressed types with their current LCOM4 values. Verified end-to-end against the real LCOM4 path (--lcom4 with an index store): a suppressed LCOM4=3 class disappears from xcode/sarif output while an identical unsuppressed twin still reports, values remain in JSON, and the suppression is listed by --report-suppressions. Claude-Session: https://claude.ai/code/session_01GaTHVDhSAx76RbLmVziLQu
📊 PR Analysis
📝 Large PR: Consider breaking this into smaller, focused PRs. Automated analysis by swift-complexity CI |
🔍 Complexity Analysis Results✅ All functions are below the complexity threshold of 15. This analysis was performed by swift-complexity itself. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends
// swift-complexity:disableto type declarations (class/struct/actor) so a reviewed low-cohesion type can be exempted from LCOM4 judgments. Previously the only workaround was--exclude, which hides the whole file's complexity violations too.Closes #36.
Syntax
Design
SuppressionParsernow takes anapplicableToscope and intersects parsed metrics with it —FunctionDetectorpassesfunctionLevel(cyclomatic/cognitive),NominalTypeDetectorpassestypeLevel(lcom4). This yields three properties at once:lcom4and never cascades to member functions (a dedicated test pins this).lcom4above a function,cyclomaticabove a class) suppresses nothing — the fail-closed contract from feat: Add inline suppression comments for complexity thresholds #35 extends naturally.lcom4toSuppressedMetric.allCaseswould have leaked"lcom4"into thesuppressedMetricsarray of bare-disabled functions, changing v1.1.0 output. A test now pins the function set to{cyclomatic, cognitive}.ClassCohesiongains an optionalsuppressedMetricsset; the LCOM4 value is still computed and shown everywhere. All three cohesion judgment sites are gated — the Xcode diagnostic, SARIF'slcom4_cohesionresults, and the CLI's threshold filtering. The exit code needs no change because LCOM4 never influenced it.--report-suppressionsnow also lists suppressed types with current LCOM4 values, and its help text mentions types.CohesionSummarystatistics andcohesionLevelclassification are deliberately unchanged — they are data, not judgments.Verification
swift test: 107 tests pass, including the first direct unit tests forNominalTypeDetector(type-level scoping fixture: bare/lcom4-scoped/unsuppressed/wrong-level/typo cases), a no-cascade test over member functions, parser scope-intersection tests, and a formatter test asserting a suppressed LCOM4=5 class produces no SARIF result and no Xcode diagnostic while remaining visible in JSON--lcom4 --index-store-path): a suppressed LCOM4=3 class disappeared fromxcode/sarifoutput while an identical unsuppressed twin still reported;--report-suppressionslisted it; JSON kept both valueslcom4leakage)swift-formatclean; markdownlint error count identical tomainhttps://claude.ai/code/session_01GaTHVDhSAx76RbLmVziLQu