Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: jsx-newline sometimes breaks with comments #3573

Open
2 tasks done
happenslol opened this issue May 9, 2023 · 3 comments · May be fixed by #3747
Open
2 tasks done

[Bug]: jsx-newline sometimes breaks with comments #3573

happenslol opened this issue May 9, 2023 · 3 comments · May be fixed by #3747

Comments

@happenslol
Copy link

Is there an existing issue for this?

  • I have searched the existing issues and my issue is unique
  • My issue appears in the command-line and not only in the text editor

Description Overview

In the following minimal example, the react/jsx-newline rule fails to parse the file:

function Test() {
  return (
    <div>
      <div />
      {/* a comment */}
    </div>
  );
}

The following error is printed on running eslint:

Oops! Something went wrong! :(

ESLint: 8.40.0

TypeError: Cannot read properties of undefined (reading 'loc')
Occurred while linting /home/happens/tmp/jsx-newline-test/test.jsx:1
Rule: "react/jsx-newline"
    at isMultilined (/home/happens/tmp/jsx-newline-test/node_modules/eslint-plugin-react/lib/rules/jsx-newline.js:23:15)
    at /home/happens/tmp/jsx-newline-test/node_modules/eslint-plugin-react/lib/rules/jsx-newline.js:111:22
    at Array.forEach (<anonymous>)
    at /home/happens/tmp/jsx-newline-test/node_modules/eslint-plugin-react/lib/rules/jsx-newline.js:87:27
    at Set.forEach (<anonymous>)
    at Program:exit (/home/happens/tmp/jsx-newline-test/node_modules/eslint-plugin-react/lib/rules/jsx-newline.js:86:27)
    at ruleErrorHandler (/home/happens/tmp/jsx-newline-test/node_modules/eslint/lib/linter/linter.js:1049:28)
    at /home/happens/tmp/jsx-newline-test/node_modules/eslint/lib/linter/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/home/happens/tmp/jsx-newline-test/node_modules/eslint/lib/linter/safe-emitter.js:45:38)

Moving the comment up a row or removing the sibling fixes the problem.

Expected Behavior

The rule should be able to correctly parse the file.

eslint-plugin-react version

v7.32.2

eslint version

v8.40.0

node version

v19.9.0

@golopot
Copy link
Contributor

golopot commented May 13, 2023

This cannot be reproduced with the default parser, can you show what parser you are using? For example running npx eslint --print-config src/index.js

@yigitlevent
Copy link

yigitlevent commented Nov 19, 2023

I'm having the same issue. Package versions and my eslint config file is below. Thanks!

Packages
"dependencies": {
    "@emotion/react": "^11.11.1",
    "@emotion/styled": "^11.11.0",
    "@mui/icons-material": "^5.14.18",
    "@mui/material": "^5.14.18",
    "axios": "^1.6.2",
    "fuse.js": "^7.0.0",
    "immer": "^10.0.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.19.0",
    "zustand": "^4.4.6"
},
"devDependencies": {
    "@types/node": "^20.9.2",
    "@types/react": "^18.2.37",
    "@types/react-dom": "^18.2.15",
    "@typescript-eslint/eslint-plugin": "^6.11.0",
    "@typescript-eslint/parser": "^6.11.0",
    "@vitejs/plugin-react-swc": "^3.5.0",
    "dotenv": "^16.3.1",
    "eslint": "^8.54.0",
    "eslint-plugin-import": "^2.29.0",
    "eslint-plugin-json": "^3.1.0",
    "eslint-plugin-react": "^7.33.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.4",
    "typescript": "^5.2.2",
    "vite": "^5.0.0"
}
ESLint Config
module.exports = {
	root: true,
	env: { browser: true, es2020: true },
	settings: {
		react: {
			version: "detect"
		}
	},
	extends: [
		"eslint:recommended",
		"plugin:import/typescript",
		"plugin:react/recommended",
		"plugin:react-hooks/recommended",
		"plugin:@typescript-eslint/recommended",
		"plugin:json/recommended"
	],
	parserOptions: {
		project: ["./tsconfig.json"]
	},
	parser: "@typescript-eslint/parser",
	ignorePatterns: ["node_modules", "dist", "build", "dist", "package.json", "tsconfig.json", "tsconfig.node.json", ".eslintrc.cjs", "vite.config.ts", "**/components_old/**/*.tsx", "**/oldStores/**/*.tsx"],
	plugins: ["import", "react", "react-hooks", "react-refresh", "@typescript-eslint", "json"],
	rules: {
		"json/*": ["error", "allowComments"],
	"import/named": "off",
	"import/newline-after-import": ["error", { count: 2 }],
	"import/no-default-export": "error",
	"import/no-unresolved": ["error", { ignore: ['\\.woff$'] }],
	"import/no-self-import": "error",
	"import/no-duplicates": "error",
	"import/order": [
		"error",
		{
			"newlines-between": "always",
			alphabetize: { "order": "asc", "caseInsensitive": true },
			groups: ["builtin", "external", "internal", ["parent", "sibling", "index", "object"], "type", "unknown"],
			pathGroups: [
				{
					pattern: "**/*.+(css|sass|less|scss|pcss|styl|woff)",
					patternOptions: { dot: true, nocomment: true },
					group: "unknown",
					position: "after"
				},
				{
					pattern: "{.,..}/**/*.+(css|sass|less|scss|pcss|styl|woff)",
					patternOptions: { dot: true, nocomment: true },
					group: "unknown",
					position: "after"
				}
			],
			warnOnUnassignedImports: true
		}
	],

	"eqeqeq": "error",
	"no-debugger": "warn",
	"eol-last": ["error", "always"],
	"prefer-const": "error",
	"no-mixed-spaces-and-tabs": "error",
	"linebreak-style": "off",
	"operator-linebreak": ["error", "before"],
	"quotes": ["error", "double"],
	"semi": ["error", "always"],
	"indent": "off",
	"no-empty": "off",
	"no-empty-function": "off",
	"no-unused-vars": "off",
	"comma-dangle": "off",
	"no-multi-spaces": ["error"],
	"no-multiple-empty-lines": "error",
	"no-multiple-empty-lines": ["error", { max: 2, maxBOF: 0 }],
	"no-restricted-imports": ["error", {
		"paths": [
			{ name: "react", importNames: ["default"], message: "Please do not import React." },
		]
	}],

	"@typescript-eslint/comma-dangle": "error",
	"@typescript-eslint/indent": ["error", "tab"],
	"@typescript-eslint/no-explicit-any": "error",
	"@typescript-eslint/no-inferrable-types": "error",
	"@typescript-eslint/no-empty-function": "error",
	"@typescript-eslint/no-empty-interface": "error",
	"@typescript-eslint/no-unsafe-declaration-merging": "error",
	"@typescript-eslint/no-unsafe-enum-comparison": "error",
	"@typescript-eslint/explicit-module-boundary-types": "error",
	"@typescript-eslint/no-duplicate-enum-values": "error",
	"@typescript-eslint/no-unused-vars": ["warn", { vars: "all", args: "after-used" }],
	"@typescript-eslint/naming-convention": [
		"error",
		{ selector: "default", format: ["camelCase"] },

		{ selector: "variable", modifiers: ["exported"], filter: { regex: "^use", match: true }, format: ["camelCase"] },
		{ selector: "variable", modifiers: ["global"], format: ["PascalCase"] },
		{ selector: "variable", format: ["camelCase"] },

		{ selector: "function", modifiers: ["exported"], filter: { regex: "^use", match: true }, format: ["camelCase"] },
		{ selector: "function", modifiers: ["global"], format: ["PascalCase"] },
		{ selector: "function", format: ["camelCase"] },

		{ selector: "parameter", format: ["camelCase"], format: null },

		{ selector: "property", format: null },
		{ selector: "property", types: ["array", "boolean", "function", "string"], format: ["camelCase", "snake_case", "PascalCase"] },

		{ selector: "classProperty", types: ["number"], format: ["camelCase"], leadingUnderscore: "allow" },

		{ selector: "property", types: ["string"], filter: { regex: "^Access-Control-Allow-Origin$", match: true }, format: null },

		{ selector: "method", format: ["camelCase"] },

		{ selector: "enumMember", format: ["PascalCase"] },
		{ selector: "typeLike", format: ["PascalCase"] },

		{ selector: "import", format: null }
	],

	"react/jsx-uses-react": "off",
	"react/react-in-jsx-scope": "off",
	"react/jsx-fragments": ["error", "element"],
	"react/jsx-filename-extension": ["warn", { extensions: [".ts", ".tsx"] }],
	"react/no-arrow-function-lifecycle": "error",
	"react/no-danger": "error",
	"react/no-deprecated": "error",
	"react/no-did-mount-set-state": "error",
	"react/no-did-update-set-state": "error",
	"react/no-direct-mutation-state": "error",
	"react/no-is-mounted": "error",
	"react/no-unused-state": "warn",
	"react/no-multi-comp": ["error", { "ignoreStateless": true }],
	"react/no-unescaped-entities": "off",
	"react/jsx-newline": ["error", { prevent: true, allowMultilines: true }],
	"react/hook-use-state": ["off", { allowDestructuredState: true }],
	"react/jsx-curly-newline": ["error", { multiline: "consistent", singleline: "consistent" }],
	"react/self-closing-comp": ["error", { component: true, html: true }],
	"react/jsx-wrap-multilines": ["error", {
		"declaration": "parens-new-line",
		"assignment": "parens-new-line",
		"return": "parens-new-line",
		"arrow": "parens-new-line",
		"condition": "ignore",
		"logical": "ignore",
		"prop": "ignore"
	}],
	"react-hooks/rules-of-hooks": "error",
	"react-hooks/exhaustive-deps": "error",
	"react-refresh/only-export-components": ["warn", { allowConstantExport: true }]
},
overrides: [
	{
		files: ["./src/store/store.ts"],
		rules: {
			"no-restricted-imports": ["error", { "paths": [{ name: "react", importNames: ["default"], message: "Please do not import React." }] }]
		}
	}
]

};

@chripi
Copy link

chripi commented Dec 2, 2023

Same issue here. It seems the problem is that

function isMultilined(node) {
  return node.loc.start.line !== node.loc.end.line;
}

is called with node being undefined.

I see that this simple change

function isMultilined(node) {
  return node?.loc.start.line !== node?.loc.end.line;
}

seems to fix the bug. Not sure if the output is correct/as expected, but at least the execution does not crash

@akulsr0 akulsr0 linked a pull request May 3, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

5 participants