{"record":{"id":"80e6cf5fbee6361a","repo":"oxc-project/oxc","slug":"name-is-a-function","errorCode":null,"errorMessage":"'{name}' is a function.","messagePattern":"'(.+?)' is a function\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/eslint/no_func_assign.rs","lineNumber":10,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_semantic::AstNode;\nuse oxc_span::Span;\n\nuse crate::{context::LintContext, rule::Rule};\n\nfn no_func_assign_diagnostic(name: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"'{name}' is a function.\"))\n        .with_help(\"Do not re-assign a function declared as a FunctionDeclaration.\")\n        .with_label(span.label(format!(\"{name} is re-assigned here\")))\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoFuncAssign;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow reassigning `function` declarations.\n    ///\n    /// This rule can be disabled for TypeScript code, as the TypeScript compiler\n    /// enforces this check.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Overwriting/reassigning a function written as a FunctionDeclaration is often indicative of","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs#L1-L28","documentation":"Diagnostic from oxlint's no-func-assign rule (ESLint port, eslint:recommended). It fires when an assignment target resolves to a symbol declared with a function declaration, overwriting the function binding. Reassigning function declarations is legal in sloppy mode but destroys the hoisted binding and confuses readers, so the rule reports \"'{name}' is a function.\" with the label '{name} is re-assigned here'.","triggerScenarios":"function calc() {} later followed by calc = otherFn;; compound writes like handler += wrap(handler) or handler ??= fallback; destructuring assignment [handler] = fns; where handler is a function declaration.","commonSituations":"Monkey-patching helpers in tests (render = mockRender); a refactor replaces a function's implementation by assigning over it instead of editing the declaration; two scripts defining the same global function name with one assigning over the other.","solutions":["Use a separate variable for the new value and keep the function binding intact.","If the binding must change, declare with let (let calc = function () {...}) instead of a function declaration.","Rename the function or the assignment target so they stop colliding.","For deliberate test monkey-patching, suppress with // oxlint-disable-next-line eslint/no-func-assign."],"exampleFix":"// before\nfunction format(input) {\n  return input;\n}\nformat = (input) => input.trim();\n\n// after\nfunction format(input) {\n  return input;\n}\nconst formatTrimmed = (input) => input.trim();","handlingStrategy":"validation","validationCode":"const fnNames = new Set([...source.matchAll(/^\\s*function\\s+(\\w+)/gm)].map((m) => m[1]));\nconst clobber = [...source.matchAll(/(\\w+)\\s*=[^=]/g)].some((m) => fnNames.has(m[1]));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat function declarations as immutable bindings.","Inject or wrap mocks in tests instead of reassigning exported functions.","Name replacement values distinctly instead of shadowing the function."],"tags":["eslint","oxlint","lint","functions","assignment"],"backgroundTag":"function-declaration-reassignment","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}