Repository navigation
Detect linter, formatter and type checker config files - #34
Merged
Merged
Conversation
Add LINTER_RULES covering 30 tools and 96 exact filenames across JavaScript, TypeScript, CSS, Python, Go, Ruby, Java, Groovy, C#/.NET and SQL, with their ignore counterparts. Every convention was verified against the tool's current official documentation. LINTER_RULES describes each tool once — languages, roles, and the files that identify it — and is expanded into the existing METADATA_RULES tables at import. Prettier alone accepts 18 config filenames carrying identical tags, so the literal form would be 18 near-duplicate lines; the table also makes the tag shape structurally guaranteed rather than a convention each entry has to remember, which is what went wrong between the pre-existing `eslint` and `SQLFluff` rules. core.py and cli.py needed no change: get_tags() reads the expanded tables, and the existing vocabulary drift test picked up all 96 rules. Eleven candidates were investigated and deliberately rejected, each of which would have been a wrong rule — revive auto-discovers only $HOME/revive.toml, a user-level path; SpotBugs, PMD and CodeNarc take arbitrarily-named files passed on the command line; Black, StandardJS and Spotless have no dedicated config file. pyproject.toml, setup.cfg, tox.ini and package.json really do hold linter config, but which tool is inside is not knowable from a path, so tagging them would mislabel nearly every repository that has one. Negative tests assert all of this stays true, and docs/linter-detection-rules.md records the sources. Tags grew 85 -> 118, filetypes 76 -> 86. All tag changes are additions or case-only (`eslint` -> `ESLint`), and SQLite LIKE is case-insensitive, so kospex's stored queries still match; a pin bump is needed only to pick up the new tags via re-sync. Two fixes this surfaced: - panopticas file reported no file type for any file typed by basename rather than by extension, because it read get_extension_filetype(), which consults only EXT_FILETYPES. `panopticas file go.mod` showed a blank file type while `assess` showed `go.mod`. The row now reads get_language(skip_shebang=True), so both commands agree; skip_shebang keeps it distinct from the Shebang Language row, and the UNKNOWN sentinel is normalised to null for the JSON contract. - check_shebang() caught only FileNotFoundError and UnicodeDecodeError, so a directory raised IsADirectoryError and a single unreadable file aborted an entire `panopticas assess` scan with PermissionError. It now catches (OSError, ValueError), covering every filesystem refusal plus a NUL byte in the path. `panopticas urls` had the identical bug one layer up and is fixed in the CLI loop, leaving extract_urls_from_file()'s documented raising behaviour intact. Passing a filename that does not exist on disk was already safe and still is. Also adds .mjs and .cjs as JavaScript and .mts and .cts as TypeScript, which were missing from EXT_FILETYPES entirely — unrelated to linters, but every file using them reported Unknown. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.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.
Adds detection for linter, formatter and type checker configuration files and their ignore counterparts — 30 tools, 96 exact filenames across JavaScript, TypeScript, CSS, Python, Go, Ruby, Java, Groovy, C#/.NET and SQL.
Every convention was verified against the tool's current official documentation.
docs/linter-detection-rules.mdrecords the inventory, the source for each tool, and what was rejected.Coverage
Eight tools have an ignore counterpart: ESLint, Prettier, Stylelint, JSHint, yapf, RuboCop, Standard, SQLFluff.
Why a table rather than 96 literal rules
LINTER_RULESdescribes each tool once — languages, roles, and the files that identify it — and is expanded into the existingMETADATA_RULEStables at import.Prettier alone accepts 18 config filenames carrying identical tags, so the literal form is 18 near-duplicate lines. More importantly the table makes the tag shape structurally guaranteed rather than a convention each entry has to remember — which is exactly what went wrong between the two pre-existing rules, where
eslint.config.jstaggedeslintand.sqlflufftaggedSQLFluff, one lowercase and one brand-cased, one with aconfigrole and one without.core.pyandcli.pyneeded no change for this:get_tags()reads the expanded tables, and the existing vocabulary drift test picked up all 96 rules.Eleven candidates rejected
Each would have been a wrong rule, and a wrong rule mislabels repositories:
$HOME/revive.toml— a user-level path, not a repository artifact.pyproject.toml,setup.cfg,tox.iniandpackage.jsongenuinely hold linter config, but which tool is inside is not knowable from a path, and detection here is path-based only. Tagging them would mislabel nearly every repository that has one. Negative tests assert all of the above stays true.Two fixes this surfaced
panopticas fileignored basename mappings. It built its File type row fromget_extension_filetype(), which consults onlyEXT_FILETYPES.panopticas file go.modshowed a blank file type whileassessshowedgo.mod;setup.cfgwas blank the same way. Now readsget_language(skip_shebang=True), so both commands agree —skip_shebangkeeps the row distinct from Shebang Language, and theUNKNOWNsentinel is normalised to null for the JSON contract. Across the 96 config filenames the row went from 55/96 resolved to 96/96.One unreadable file aborted a whole scan.
check_shebang()caughtFileNotFoundErrorandUnicodeDecodeErrorbut not the other waysopen()fails, so a directory raisedIsADirectoryErrorand a single unreadable file killed an entirepanopticas assessrun withPermissionError. Now catches(OSError, ValueError)— every filesystem refusal, plus a NUL byte in the path.panopticas urlshad the identical bug one layer up, fixed in the CLI loop soextract_urls_from_file()'s documented raising behaviour stays intact. Passing a filename that does not exist on disk was already safe and still is.Also: four missing extensions
.mjsand.cjsare now JavaScript,.mtsand.ctsTypeScript. These were absent fromEXT_FILETYPESentirely, so every file using them reportedUnknown— unrelated to linters, but they surfaced here because config authors use them to escape the"type"field inpackage.json.Matches GitHub Linguist, which types all four as
programming.kospex impact
Tags grew 85 → 118, filetypes 76 → 86. Every tag change is an addition or case-only (
eslint→ESLint), and SQLiteLIKEis case-insensitive, so stored queries still match. Nothing was renamed in a way that changes matching and nothing removed. A pin bump is needed only to pick up the new tags, which requires a re-sync —last_panopticas_versionhandles that.Testing
686 tests pass.
tests/test_linter_detection.pyis new (141 tests): table integrity, expansion into eachMETADATA_RULEStable, tags per language, the config/ignore split, filetype resolution for all 96 filenames, and negative guards for each rejected convention. Nine robustness tests added acrosstest_panopticas.pyandtest_cli_json.py, eight of which failed before the fixes.Version bumped to 0.0.20; CHANGELOG left as
[Unreleased].🤖 Generated with Claude Code