solidjs-community / eslint-plugin-solid

Solid-specific linting rules for ESLint.
MIT License
206 stars 24 forks source link

solid/reactivity causes eslint crash [Error: This should never happen] ScopeStack.findDeepestDeclarationScope #110

Closed aronmal closed 6 months ago

aronmal commented 8 months ago

Describe the bug When running eslint it's crashing, I can fix it when I removing a helper function.

Console: ``` > eslint --fix "src/**/*.{ts,tsx,js,jsx}" Oops! Something went wrong! :( ESLint: 8.52.0 Error: This should never happen Occurred while linting /home/aronmal/Documents/Github/praxis-siebers/src/frontend-helpers/formReducer.ts:72 Rule: "solid/reactivity" at ScopeStack.findDeepestDeclarationScope (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint-plugin-solid@0.13.0_eslint@8.52.0_typescript@5.2.2/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:30:19) at ScopeStack.pushUniqueSignal (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint-plugin-solid@0.13.0_eslint@8.52.0_typescript@5.2.2/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:48:49) at handleTrackedScopes (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint-plugin-solid@0.13.0_eslint@8.52.0_typescript@5.2.2/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:200:40) at onFunctionExit (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint-plugin-solid@0.13.0_eslint@8.52.0_typescript@5.2.2/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:331:25) at ruleErrorHandler (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint@8.52.0/node_modules/eslint/lib/linter/linter.js:1091:28) at /home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint@8.52.0/node_modules/eslint/lib/linter/safe-emitter.js:45:58 at Array.forEach () at Object.emit (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint@8.52.0/node_modules/eslint/lib/linter/safe-emitter.js:45:38) at NodeEventGenerator.applySelector (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint@8.52.0/node_modules/eslint/lib/linter/node-event-generator.js:297:26) at NodeEventGenerator.applySelectors (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/eslint@8.52.0/node_modules/eslint/lib/linter/node-event-generator.js:326:22)  ELIFECYCLE  Command failed with exit code 2. ```
My helper function: ```tsx export interface FormFieldType { fieldName: string field: string value: string alertMessage: string type: string required: boolean } export type FormObjectType = FormFieldType[] interface setValue { type: "setValue" payload: { field: string; value: string } } interface setAlert { type: "setAlert" payload: { field: string; alertMessage: string } } interface reset { type: "reset" } interface clearAlerts { type: "clearAlerts" } export type FormObjectDispatchType = setValue | setAlert | reset | clearAlerts export const initialFormObject: FormObjectType = [ { fieldName: "Ihr Name", field: "name", value: "", alertMessage: "", type: "input", required: true, }, { fieldName: "Ihre E-Mail", field: "email", value: "", alertMessage: "", type: "input", required: true, }, { fieldName: "Ihre Telefonnummer", field: "telephone", value: "", alertMessage: "", type: "input", required: false, }, { fieldName: "Betreff", field: "subject", value: "", alertMessage: "", type: "input", required: true, }, { fieldName: "Ihre Nachricht", field: "message", value: "", alertMessage: "", type: "textarea", required: true, }, ] export default function formObjectDispatch( formObject: FormObjectType, action: FormObjectDispatchType, ) { switch (action.type) { case "setValue": { const { field, value } = action.payload const fieldMatch = formObject.findIndex((props) => props.field === field) const fieldProps = formObject[fieldMatch] const result = Object.assign([...formObject], { [fieldMatch]: { ...fieldProps, value, alertMessage: "", }, }) return result } case "setAlert": { const { field, alertMessage } = action.payload const fieldMatch = formObject.findIndex((props) => props.field === field) const fieldProps = formObject[fieldMatch] const result = Object.assign([...formObject], { [fieldMatch]: { ...fieldProps, alertMessage, }, }) return result } case "reset": { return initialFormObject } case "clearAlerts": { const result = formObject.map((obj) => ({ ...obj, alertMessage: "" })) return result } default: return formObject } } ```

To Reproduce Have the helper function in a file in the src dir of the solid-start project.

Expected behavior lint and not crash

Screenshots See Console output.

Environment (please complete the following information):

Additional context Ask if you need more information. I would want to help, but I don't know how this plugin works in the background.

joshwilsonvu commented 8 months ago

That's bizarre! You're not even using any Solid APIs here. I'll look into this when I get some time.

Seems like there's an edge case with the reactivity rule's inner workings—tricky code, so not really something I'd ask you to worry about, though thanks for offering!

joshwilsonvu commented 6 months ago

Whew, this was a tough one!

You managed to hit several different edge cases that only cause a problem when combined:

The problem was a subtle timing issue, and is fixed by reordering a few lines 😅