fix(ego-lint): skip signal callback bodies in constructor init check#129
Merged
fix(ego-lint): skip signal callback bodies in constructor init check#129
Conversation
Signal callbacks (.connect(), .connectObject()) inside constructors are deferred — they don't execute during construction, so Shell globals inside them are not init-time violations. Add filter_signal_callbacks() to exclude callback body lines while still checking the .connect() line itself (the receiver may be a Shell global accessed at construction time). Closes #118 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ZviBaratz
commented
Mar 10, 2026
Owner
Author
ZviBaratz
left a comment
There was a problem hiding this comment.
Review: Approve ✓
Clean, well-scoped fix. The semantic reasoning is correct — signal callbacks are deferred, not executed at construction time — and the implementation is consistent with existing brace-depth tracking patterns in the file.
What's good:
filter_signal_callbacks()correctly keeps the.connect()line (receiver IS evaluated at construction time) while filtering callback body lines- Test fixture covers both
.connect()and.connectObject(), plus a direct Shell global access that should still be flagged - No regressions — existing init fixtures unaffected
Minor observations (non-blocking):
- Multi-line
.connectObject()with callback on next line — if the call is split so the() => {starts on a different line than.connectObject(, the brace count on the.connect()line is 0, socallback_depthstays 0 and the callback body won't be filtered. Conservative behavior (flags when uncertain), which is the right default - Single-line inline callbacks —
this.connect('notify', () => Main.panel.x)keeps the whole line, soMain.panelgets flagged even though it's deferred. Unlikely in practice inside constructors .connect_after()not matched by the regex — very rare, fine to address if/when it causes a real FP
3 tasks
ZviBaratz
added a commit
that referenced
this pull request
Mar 11, 2026
…es (#131) ## Summary - Re-ran field tests after merging PRs #123, #126, #127, #128, #129, #130 which addressed ~22 false positives across 7 rules - Updated all 10 baselines to current ego-lint output (`a441201`) - Reclassified 92 findings as `resolved` (no longer emitted) - Annotated 9 new findings across 5 extensions - Updated README with refreshed metrics ### Results comparison | Metric | Before (03-08) | After (03-10) | Change | |--------|----------------|---------------|--------| | PASS | 1,849 | 1,917 | +68 | | FAIL | 47 | 30 | -17 | | WARN | 467 | 461 | -6 | | SKIP | 202 | 167 | -35 | | Strict precision | 81.5% | 85.1% | +3.6pp | | Lenient precision | 83.3% | 86.7% | +3.4pp | | Active FPs | 80 | 58 | -22 | | Resolved | 9 | 92 | +83 | ## Test plan - [x] All 734 tests pass - [x] Zero unannotated findings across all 10 extensions - [x] 100% annotation coverage maintained 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
ZviBaratz
pushed a commit
that referenced
this pull request
Mar 25, 2026
🤖 I have created a release *beep* *boop* --- ## [0.1.1](v0.1.0...v0.1.1) (2026-03-25) ### Features * add automated field test pipeline ([#34](#34)) ([6d906d6](6d906d6)) * add parse-review-results.py for structured finding extraction ([#56](#56)) ([2083bc7](2083bc7)) * **ego-lint:** add --show and --report flags for output filtering ([#111](#111)) ([5fc5a6e](5fc5a6e)) * **ego-lint:** add .destroy without parentheses detection (R-LIFE-23) ([#50](#50)) ([f9c035b](f9c035b)) * **ego-lint:** add compat-downgrade for version-aware deprecated API gating ([#104](#104)) ([3e00e6e](3e00e6e)) * **ego-lint:** add D-Bus connectSignal leak detection (R-LIFE-25) ([#59](#59)) ([c54d848](c54d848)) * **ego-lint:** add lifecycle leak detection (R-LIFE-21, R-LIFE-22, R-LIFE-24) ([#48](#48)) ([10f6bbd](10f6bbd)) * **ego-lint:** add module-scope mutable state detection (R-LIFE-26) ([#60](#60)) ([9c5d2e3](9c5d2e3)) * **ego-lint:** add module-scope prototype mutation detection (R-LIFE-27) ([#83](#83)) ([0d2df8d](0d2df8d)) * **ego-lint:** add notification urgency abuse detection (R-QUAL-36) ([#49](#49)) ([546bd10](546bd10)) * **ego-lint:** detect indirect prototype mutation via function calls ([#114](#114)) ([bce145b](bce145b)) * **ego-review:** eliminate redundant work by referencing ego-lint findings ([787261a](787261a)) ### Bug Fixes * **ego-field-test:** fix IFS collapse and commit-hash fetch failures ([f4b480f](f4b480f)) * **ego-field-test:** indent multi-line expressions in json_extract wrapper ([ae650be](ae650be)) * **ego-field-test:** resolve imports/no-gtk-in-extension false positives ([#128](#128)) ([8e39d98](8e39d98)) * **ego-lint:** add missing CSS shell classes to KNOWN_SHELL_CLASSES ([#54](#54)) ([c6c61be](c6c61be)) * **ego-lint:** add replacement-pattern to R-VER rules for version-compat suppression ([#84](#84)) ([d7051cf](d7051cf)) * **ego-lint:** add skip-comments to R-LOG-03 to prevent block comment FPs ([#132](#132)) ([f138a43](f138a43)) * **ego-lint:** add src/ layout license fallback and UUID-dir skip ([#30](#30)) ([9f616ec](9f616ec)) * **ego-lint:** add src/ metadata.json fallback for build-system extensions ([#24](#24)) ([145b639](145b639)) * **ego-lint:** add src/schemas/ fallback for non-standard layouts ([#80](#80)) ([4d00563](4d00563)) * **ego-lint:** add version-compat suppression and calibrate severities ([#69](#69)) ([5442f13](5442f13)) * **ego-lint:** anchor Gdk import pattern to avoid matching GdkPixbuf ([#101](#101)) ([0e07043](0e07043)) * **ego-lint:** auto-detect and exclude vendored files from all lint checks ([#152](#152)) ([81d48cd](81d48cd)) * **ego-lint:** avoid false FAIL when enum-id precedes schema-id in check-schema ([#148](#148)) ([8399589](8399589)) * **ego-lint:** correct R-SLOP-01 provenance post-filter matching ([#85](#85)) ([ff05efb](ff05efb)) * **ego-lint:** deduplicate prototype-override warnings ([#32](#32)) ([431ad18](431ad18)) * **ego-lint:** detect compiled TypeScript and suppress noisy rules ([#52](#52)) ([1b1b5d4](1b1b5d4)) * **ego-lint:** downgrade css/shell-class-override from FAIL to WARN ([#100](#100)) ([4aa6f2f](4aa6f2f)) * **ego-lint:** downgrade css/shell-class-override from FAIL to WARN ([#112](#112)) ([dc83726](dc83726)) * **ego-lint:** downgrade missing LICENSE from FAIL to WARN ([#110](#110)) ([fe0eab7](fe0eab7)) * **ego-lint:** enhance GSettings signal leak detection for helper classes ([#87](#87)) ([21f7390](21f7390)) * **ego-lint:** exclude preferences/ dirs from gsettings-signal-leak ([#102](#102)) ([60b15d3](60b15d3)) * **ego-lint:** exclude service/ daemon code from extension-specific checks ([#147](#147)) ([2962779](2962779)) * **ego-lint:** exclude service/ dir from R-DEPR-06 and R-DEPR-10 ([#99](#99)) ([ed40e47](ed40e47)) * **ego-lint:** exempt isLocked guard from impossible-state and session-modes checks ([#31](#31)) ([69c6254](69c6254)) * **ego-lint:** expand CSS shell-class list from GNOME Shell SCSS source ([#57](#57)) ([311da35](311da35)) * **ego-lint:** expand init/shell-modification and constructor-resources exemptions ([#88](#88)) ([14d0ca3](14d0ca3)) * **ego-lint:** expand R-SLOP-24 guard for system schema identifiers ([#139](#139)) ([1a58b06](1a58b06)) * **ego-lint:** expand R-SLOP-24 guard for system schemas and multi-line constructors ([#135](#135)) ([27787a6](27787a6)) * **ego-lint:** expand R-SLOP-38 guard for domain-specific identifiers ([#141](#141)) ([4aaf615](4aaf615)) * **ego-lint:** handle async arrow functions and GObject branch in check-init.py ([#55](#55)) ([9d6654a](9d6654a)) * **ego-lint:** make R-LIFE-25 bare connectSignal always FAIL regardless of disconnectSignal elsewhere ([#91](#91)) ([05523f9](05523f9)) * **ego-lint:** narrow R-LIFE-25 auto-cleanup to D-Bus-specific disconnectSignal ([#65](#65)) ([8263cbc](8263cbc)) * **ego-lint:** propagate strip_comments newline preservation to all scripts ([#61](#61)) ([4178a5a](4178a5a)) * **ego-lint:** recognize alternative cleanup methods in resource tracking ([#130](#130)) ([bbc0f51](bbc0f51)) * **ego-lint:** recognize array-based signal ID storage in gsettings-signal-leak ([#64](#64)) ([99c89c0](99c89c0)) * **ego-lint:** recognize full GPL license text in license check ([#127](#127)) ([38cbb59](38cbb59)) * **ego-lint:** reduce false positives for R-SLOP-35, R-SEC-03, R-SLOP-13 ([#123](#123)) ([860fc0b](860fc0b)) * **ego-lint:** reduce init-time safety false positives ([#21](#21)) ([e46e2df](e46e2df)) * **ego-lint:** reduce Media Controls false positives ([#23](#23)) ([7cea626](7cea626)) * **ego-lint:** reduce resource-tracking FPs for blur-my-shell ([#143](#143)) ([99c5903](99c5903)) * **ego-lint:** reduce resource-tracking/no-destroy-method false positives ([#86](#86)) ([30bbeac](30bbeac)) * **ego-lint:** reduce signal-balance false positives ([#13](#13)) ([900b133](900b133)) * **ego-lint:** reduce Tiling Shell false positives ([#22](#22)) ([62c5509](62c5509)) * **ego-lint:** remove Shell.ActionMode.ALL from hallucinated-API list ([#149](#149)) ([715519f](715519f)) * **ego-lint:** scope init/shell-modification to Extension class constructors ([#140](#140)) ([5e86aa6](5e86aa6)) * **ego-lint:** skip file-structure checks for compiled TypeScript extensions ([#103](#103)) ([f15ddcb](f15ddcb)) * **ego-lint:** skip JSDoc block comments in R-WEB-06 document.* check ([#150](#150)) ([fc10806](fc10806)) * **ego-lint:** skip R-LOG-03 in resources/ and detect Promise-returning methods in catch-on-sync ([#145](#145)) ([7d76ee5](7d76ee5)) * **ego-lint:** skip signal callback bodies in constructor init check ([#129](#129)) ([d1fa661](d1fa661)) * **ego-lint:** split R-SLOP-11 to fix false positive on GLib.source_remove() ([#126](#126)) ([a441201](a441201)) * **ego-lint:** suppress R-QUAL-28 for distinct getSettings() schema arguments ([#81](#81)) ([f8e1da7](f8e1da7)) * **ego-lint:** suppress R-VER46-01/02 for ShellVersion-guarded else branches ([#151](#151)) ([614883e](614883e)) * **ego-lint:** tighten R-SLOP-38 to reduce over-long identifier false positives ([#82](#82)) ([fe88f1b](fe88f1b)) * **ego-lint:** verify R-VER48-02 guard matches Config.PACKAGE_VERSION ([#133](#133)) ([6dfeca1](6dfeca1)) * **ego-lint:** widen R-VER48-02 guard-window for distant version checks ([#53](#53)) ([5ae31e0](5ae31e0)) ### Documentation * add ego-review pipeline efficiency design spec ([56bcdc3](56bcdc3)) * add field test reports for Tiling Shell and Media Controls ([#25](#25)) ([f8b55f7](f8b55f7)) * add field-tests/README.md with extension catalog and results ([#67](#67)) ([22fc27c](22fc27c)) * add missing skill labels and fix issue template auto-labels ([782c7b4](782c7b4)) * add resource-tracking FP reduction design spec ([a7e0a2c](a7e0a2c)) * **ego-field-test:** add 03-08 regression report, update baselines and annotations ([c5b823e](c5b823e)) * **ego-field-test:** add version info to README extension catalog and update to 03-08 ([bdb4919](bdb4919)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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
filter_signal_callbacks()tocheck-init.pythat excludes signal callback body lines (.connect(),.connectObject()) from the constructor init-time check, while still checking the.connect()line itself (the receiver may be a Shell global accessed at construction time)init-constructor-signal@testwith both.connect()and.connectObject()callbacks containing Shell globals, plus a direct Shell global access that should still be flaggedContext
Issue #118 identified 8 FPs for
init/shell-modificationacross tiling-shell and v-shell. Research showed that 6 of 8 were already resolved by prior PRs (#21 scoped constructor checks to extension.js, #88 added arrow fn exemption). The remaining 2 (tiling-shellglobalState.jsconstructor signal callbacks) are addressed by this PR.Signal callbacks are deferred — they don't execute during construction, only when the signal fires at runtime. The
.connect()line itself is kept because the receiver object (e.g.,Main.panel.connect(...)) IS accessed immediately during construction.Test plan
init-constructor-signal@testverifies:.connect()callback body is NOT flagged (lines 15-17).connectObject()callback body is NOT flagged (lines 21-24)init-time-safety,init-helper-constructor,init-modification,constructor-gobjectCloses #118
🤖 Generated with Claude Code