@colrealpro/react-luau-doctor 0.19.1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Added
6
+
7
+ - VS Code extension with live diagnostics and hover explanations, requiring no CLI or Bun installation
8
+ - Quick fixes to explain findings, add inline disables, or disable rules in project config
9
+ - Optional background scanning of unopened files
10
+ - Autocomplete and validation for `react-luau-doctor.config.json`, with a schema in both packages
11
+
12
+ ### New rules
13
+
14
+ - `react-luau/no-mutating-state-updater` catches mutations of previous state in updater callbacks
15
+ - `react-luau/no-call-component-as-function` catches direct calls to component functions
16
+ - `react-luau/no-create-binding-in-render` catches bindings recreated during render
17
+ - `react-luau/no-binding-getvalue-in-render` catches binding snapshots read during render, except for ref initialization
18
+ - `react-luau/usememo-must-return` catches memo callbacks that return no value
19
+ - `react-luau/no-static-name-prop` suggests child table keys instead of static Roblox `Name` props
20
+
21
+ ### Fixed
22
+
23
+ - Restored per-file CLI progress while parsing effects and sped up worker shutdown
24
+ - `no-set-state-in-render` catches setters in prop expressions and local initializers, including aliases
25
+ - `exhaustive-deps` follows dependency table aliases and handles shadowed module locals correctly
26
+ - `no-prop-mutation` catches prop mutations in nested functions and callbacks
27
+ - `no-array-index-as-key` uses collection shapes and types to distinguish array positions from dictionary keys
28
+ - `rules-of-hooks` accepts loops over provably static module tables
29
+ - `prefer-binding-over-state` skips custom component props proven incompatible with bindings
30
+
3
31
  ## 0.19.1
4
32
 
5
33
  ### Changed
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 ColRealPro
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ColRealPro
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,135 +1,148 @@
1
- # React-Luau Doctor
2
-
3
- Find React-Luau mistakes before they reach your Roblox UI.
4
-
5
- React-Luau Doctor checks `.lua` and `.luau` source files for hook mistakes, missing cleanup, render side effects, and avoidable rerenders. Findings include a category, severity, source location, and repair guidance. The `why` command explains individual findings and shows suggested changes where available.
6
-
7
- This beta CLI runs with Bun and analyzes React-Luau source on your computer or CI runner. It does not run inside Roblox Studio, analyze JavaScript/TypeScript React, or edit your code automatically.
8
-
9
- ## Get started
10
-
11
- React-Luau Doctor requires [Bun](https://bun.com/) 1.4.0 or newer. Run it directly from npm with either Bun or npm:
12
-
13
- ```bash
14
- bunx @colrealpro/react-luau-doctor .
15
- ```
16
-
17
- ```bash
18
- npx @colrealpro/react-luau-doctor .
19
- ```
20
-
21
- `npx` still requires Bun to be installed because the React-Luau Doctor CLI itself runs with Bun.
22
-
23
- For a reusable `react-luau-doctor` command, install it globally with Bun:
24
-
25
- ```bash
26
- bun add --global @colrealpro/react-luau-doctor
27
- react-luau-doctor .
28
- react-luau-doctor . --verbose
29
- ```
30
-
31
- To work on React-Luau Doctor itself, clone the repository and use Bun for development:
32
-
33
- ```bash
34
- git clone https://github.com/colrealpro/react-luau-doctor.git
35
- cd react-luau-doctor
36
- bun install --frozen-lockfile
37
- bun run build
38
- bun run ci
39
- ```
40
-
41
- ## Read a finding
42
-
43
- For example, this component changes a prop during render:
44
-
45
- ```luau
46
- local React = require(script.Parent.React)
47
-
48
- local function Label(props)
49
- props.text = "Changed"
50
- return React.createElement("TextLabel", { Text = props.text })
51
- end
52
-
53
- return Label
54
- ```
55
-
56
- Doctor reports `react-luau/no-prop-mutation`. Compute a local value instead of writing to `props`.
57
-
58
- ```bash
59
- react-luau-doctor why src/Label.luau:4
60
- react-luau-doctor rules explain react-luau/no-prop-mutation
61
- ```
62
-
63
- Suggested changes are review guidance. Some are exact previews, others are example patterns that need adapting to your component.
64
-
65
- ## What it checks
66
-
67
- The rule catalog covers correctness, hooks, effects, performance, Roblox behavior, and architecture. Checks include conditional hooks, incomplete dependency tables, connections without cleanup, state updates during render, fresh props crossing memo boundaries, and externally updated state that may be better represented by a Binding.
68
-
69
- ```bash
70
- react-luau-doctor rules list
71
- react-luau-doctor . --category Hooks
72
- react-luau-doctor . --blocking error
73
- ```
74
-
75
- Errors are the highest severity. Warnings identify likely problems, while suggestions include lower-confidence findings that deserve review. You can override each rule's severity or disable it. A clean report is not proof of runtime correctness, and the score is a heuristic, not a performance measurement.
76
-
77
- See the [rule catalog](docs/rules.md) and [analysis limits](docs/analysis.md).
78
-
79
- ## Check a change
80
-
81
- ```bash
82
- react-luau-doctor . --scope changed --base main
83
- react-luau-doctor . --scope lines --base main
84
- react-luau-doctor . --staged
85
- react-luau-doctor . --json-out doctor-report.json
86
- ```
87
-
88
- `changed` compares findings against a Git base. `lines` keeps findings that overlap changed lines. `--staged` reads index content, so later unstaged edits do not affect the checked file contents.
89
-
90
- ## Add CI
91
-
92
- From your Roblox repository:
93
-
94
- ```bash
95
- react-luau-doctor ci install --yes
96
- ```
97
-
98
- Commit the generated `.github/workflows/react-luau-doctor.yml`. The workflow pins the exact npm version of React-Luau Doctor that generated it and runs that package with Bun, so your repository does not need to vendor the analyzer or its parser assets.
99
-
100
- By default, pull requests receive advisory findings without failing the check. Enable a gate with:
101
-
102
- ```bash
103
- react-luau-doctor ci config --blocking error --yes
104
- ```
105
-
106
- [CI setup](docs/ci.md) explains permissions, fork PRs, updates, outputs, and GitLab support. Local tests exercise reporting against a simulated GitHub API. A real GitHub Actions run is still required to validate your repository's permissions and runner behavior.
107
-
108
- ## Configure a project
109
-
110
- Create `react-luau-doctor.config.json` in the directory where you run scans:
111
-
112
- ```json
113
- {
114
- "include": ["src/**/*.luau"],
115
- "ignore": ["src/generated/**"],
116
- "rules": {
117
- "react-luau/no-array-index-as-key": "off",
118
- "react-luau/exhaustive-deps": "error"
119
- }
120
- }
121
- ```
122
-
123
- Use narrow inline suppressions when an individual finding is intentional:
124
-
125
- ```luau
126
- -- react-luau-doctor-disable-next-line no-array-index-as-key
127
- ```
128
-
129
- See the [CLI and configuration reference](docs/cli.md) for scanning, reporting, cache controls, and suppression syntax.
130
-
131
- ## Contribute
132
-
133
- Read [development and release checks](docs/development.md). For a false positive or missed issue, open an [issue](https://github.com/colrealpro/react-luau-doctor/issues) with the smallest Luau example you can share, the tool version, and the relevant configuration.
134
-
135
- MIT licensed. Inspired by [React Doctor](https://github.com/millionco/react-doctor); not affiliated with its authors, Roblox, or the React-Luau maintainers. See [third-party notices](THIRD_PARTY_NOTICES.md) for parser attribution.
1
+ <p align="center">
2
+ <img src="editors/vscode/Icon.png" alt="React-Luau Doctor icon" width="128" />
3
+ </p>
4
+
5
+ <h1 align="center">React-Luau Doctor</h1>
6
+
7
+ <p align="center">
8
+ Static analysis tool for React-Luau codebases. It helps identify potential issues, enforce best practices, and improve React code quality.
9
+ </p>
10
+
11
+ <br>
12
+
13
+ React-Luau Doctor scans your codebase and finds mistakes in hooks, effects, state management, and performance. Rules are built specifically around React-Luau patterns, including problems that can't be caught by traditional typechecking or linting. It works as a CLI or CI tool. Editor diagnostics can also be provided through the [LSP](docs/lsp.md) extension
14
+
15
+ ## Getting started
16
+
17
+ React-Luau Doctor requires [Bun](https://bun.com/) 1.4.0 or newer. You can run it directly from npm with:
18
+
19
+ ```bash
20
+ npx @colrealpro/react-luau-doctor
21
+ ```
22
+
23
+ or install it globally and run it normally:
24
+
25
+ ```bash
26
+ bun add --global @colrealpro/react-luau-doctor
27
+ react-luau-doctor
28
+ ```
29
+
30
+ This will create a short overview of your project, and report the highest severity issues, you can add `--verbose` to see all the findings
31
+
32
+ ## Examples
33
+
34
+ ```lua
35
+ local React = require("..path/to/React")
36
+ local RunService = game:GetService("RunService")
37
+
38
+ local function PlayerList(props)
39
+ local playerCount, setPlayerCount = React.useState(0)
40
+ local absolutePosition, setAbsolutePosition = React.useState(
41
+ props.container.AbsolutePosition
42
+ )
43
+
44
+ local labelText = React.useMemo(function()
45
+ return `Players: {playerCount}`
46
+ end, { playerCount })
47
+
48
+ React.useEffect(function()
49
+ setPlayerCount(#props.players)
50
+ end, { props.players })
51
+
52
+ React.useEffect(function()
53
+ props.container:GetPropertyChangedSignal("AbsolutePosition"):Connect(function()
54
+ setAbsolutePosition(props.container.AbsolutePosition)
55
+ end)
56
+ end, { props.container })
57
+
58
+ if props.hidden then
59
+ return nil
60
+ end
61
+
62
+ React.useEffect(function()
63
+ print(props.title)
64
+ end, { props.title })
65
+
66
+ return React.createElement("TextLabel", {
67
+ Text = labelText,
68
+ Position = UDim2.fromOffset(absolutePosition.X, absolutePosition.Y),
69
+ })
70
+ end
71
+ ```
72
+
73
+ React-Luau Doctor would report the following for this component:
74
+
75
+ ```
76
+ src/PlayerList.lua
77
+
78
+ X error Hook React.useEffect may run after an earlier reachable return,
79
+ so some renders can execute fewer hooks.
80
+ react-luau/rules-of-hooks
81
+
82
+ ! warning setPlayerCount() stores a value derived from props inside an effect.
83
+ react-luau/no-derived-state-effect
84
+
85
+ ! warning State absolutePosition mirrors AbsolutePosition and only feeds
86
+ presentation updates, so React reconciliation is acting as an
87
+ unnecessary host-property feedback step.
88
+ react-luau/prefer-binding-over-state
89
+
90
+ ! warning Effect creates a connection or subscription without matching cleanup.
91
+ react-luau/effect-needs-cleanup
92
+
93
+ ! warning useMemo caches a trivial derived value.
94
+ react-luau/rerender-unnecessary-usememo
95
+ ```
96
+
97
+ ## Editor support
98
+
99
+ React-Luau Doctor provides a LSP extension for VS Code
100
+
101
+ The LSP uses the same analysis as the CLI, and updates findings in real time as you edit your code
102
+
103
+ See [LSP](docs/lsp.md) for installation and configuration
104
+
105
+ ## CI
106
+
107
+ React-Luau Doctor also provides a CI that can be used to run analysis on your codebase and report findings in PRs, or be used to block merging if doctor finds issues (can't promise satisfaction on blocking merging though yet)
108
+
109
+ Install it with:
110
+
111
+ ```bash
112
+ react-luau-doctor ci install
113
+ ```
114
+
115
+ It will bring you through a couple options, you can skip it and use the defaults by adding `--yes` to the command
116
+
117
+ ## Configuring rules
118
+
119
+ Create a `react-luau-doctor.config.json` file in your project:
120
+
121
+ ```json
122
+ {
123
+ "ignore": [
124
+ "**/*.story.lua",
125
+ "**/*.story.luau"
126
+ ],
127
+ "rules": {
128
+ "react-luau/no-array-index-as-key": "off",
129
+ "react-luau/exhaustive-deps": "error"
130
+ }
131
+ }
132
+ ```
133
+
134
+ This will let you enable and disable some rules or change their severity to your liking if you dislike some of the rules.
135
+
136
+ Inline disables can also be used when a finding is intentional:
137
+ ```lua
138
+ -- react-luau-doctor-disable-next-line no-array-index-as-key
139
+ ```
140
+
141
+ ## Contributing
142
+
143
+ All contributions are welcome! Bug fixes, new rules, improvements to existing rules, and documentation changes are all appreciated!
144
+
145
+ Feel free to open an issue for bugs or feature requests, or submit a pull request
146
+
147
+
148
+ MIT licensed. Inspired by [React Doctor](https://github.com/millionco/react-doctor); not affiliated with its authors, Roblox, or the React-Luau maintainers. See [third-party notices](THIRD_PARTY_NOTICES.md) for parser attribution.
@@ -1,18 +1,25 @@
1
- # Third-party notices
2
-
3
- ## tree-sitter-luau
4
-
5
- This project redistributes `tree-sitter-luau.wasm` from
6
- `tree-sitter-grammars/tree-sitter-luau`, version 1.2.0.
7
-
8
- The grammar is MIT licensed. Its license text is included at
9
- `vendor/tree-sitter-luau.LICENSE`.
10
-
11
- Project: https://github.com/tree-sitter-grammars/tree-sitter-luau
12
-
13
- ## web-tree-sitter
14
-
15
- The runtime parser is provided by `web-tree-sitter`, which is MIT licensed.
16
- Its license is installed with the npm dependency.
17
-
18
- Project: https://github.com/tree-sitter/tree-sitter
1
+ # Third-party notices
2
+
3
+ ## tree-sitter-luau
4
+
5
+ This project redistributes `tree-sitter-luau.wasm` from
6
+ `tree-sitter-grammars/tree-sitter-luau`, version 1.2.0.
7
+
8
+ The grammar is MIT licensed. Its license text is included at
9
+ `vendor/tree-sitter-luau.LICENSE`.
10
+
11
+ Project: https://github.com/tree-sitter-grammars/tree-sitter-luau
12
+
13
+ ## web-tree-sitter
14
+
15
+ The runtime parser is provided by `web-tree-sitter`, which is MIT licensed.
16
+ Its license is installed with the npm dependency.
17
+
18
+ Project: https://github.com/tree-sitter/tree-sitter
19
+
20
+ ## jsonc-parser
21
+
22
+ Project config edits use Microsoft's MIT-licensed `jsonc-parser`
23
+ Its license is installed with the npm dependency and included in the VS Code extension at `vendor/jsonc-parser.LICENSE`
24
+
25
+ Project: https://github.com/microsoft/node-jsonc-parser