Repository: sindresorhus/eslint-plugin-unicorn (JavaScript)

Issue:
number-literal-case breaks with bigints
There isn't a good way to write hex big int literals with this rule enabled.

`0x7Fn` is marked as an error presumably because of the lower case `n`.


Discussion:
It was  fixed long time ago #490, are you using old version?
Ah, maybe you are using a old version of Node.js? Maybe there is actually something wrong in that rule.

Can you share what version of Node.js and what parser  you are using? That can help
Sorry for the delayed response. and thanks for the quick reply @fisker!

I dug into it a bit more, and I am seeing the same thing with multiple versions of node (14.9.0,  12.18.3).  All my direct dependencies are up to date (but possible some nested dependencies are not), but there is only one version of eslint-plugin-unicorn and it is 21.0.0.

Looking at the actual rule, the issue seems to be that for BigInts when it grabs the bigint value for a bigint hex literal here https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/rules/number-literal-case.js#L16, it is a base 10 string rather than a hex string.  (eg. `0x7fn` will be `'127'`) which means the "fixed" version it compares against will be `127n`. 
Located the problem, broken on `@typescript-eslint/parser`, is this the parser you use?
yup, it is! 
Fixed in #815



Patch:
diff --git a/rules/number-literal-case.js b/rules/number-literal-case.js
index 737b68129b..834c319001 100644
--- a/rules/number-literal-case.js
+++ b/rules/number-literal-case.js
@@ -1,13 +1,17 @@
 'use strict';
 const getDocumentationUrl = require('./utils/get-documentation-url');
 
-const fix = (value, isBigInt) => {
-	value = value.toLowerCase();
-	if (value.startsWith('0x')) {
-		value = '0x' + value.slice(2).toUpperCase();
+const fix = (raw, isBigInt) => {
+	let fixed = raw.toLowerCase();
+	if (fixed.startsWith('0x')) {
+		fixed = '0x' + fixed.slice(2).toUpperCase();
+
+		if (isBigInt) {
+			fixed = fixed.slice(0, -1) + 'n';
+		}
 	}
 
-	return `${value}${isBigInt ? 'n' : ''}`;
+	return fixed;
 };
 
 const create = context => {
@@ -20,7 +24,7 @@ const create = context => {
 				return;
 			}
 
-			const fixed = fix(isBigInt ? bigint : raw, isBigInt);
+			const fixed = fix(raw, isBigInt);
 
 			if (raw !== fixed) {
 				context.report({


Test patch:
diff --git a/test/number-literal-case.js b/test/number-literal-case.js
index 83732a6421..8bab11e530 100644
--- a/test/number-literal-case.js
+++ b/test/number-literal-case.js
@@ -11,18 +11,31 @@ const ruleTester = avaRuleTester(test, {
 		ecmaVersion: 2020
 	}
 });
+const babelRuleTester = avaRuleTester(test, {
+	parser: require.resolve('babel-eslint')
+});
+const typescriptRuleTester = avaRuleTester(test, {
+	parser: require.resolve('@typescript-eslint/parser')
+});
 
 const error = {
 	message: 'Invalid number literal casing.'
 };
 
-// TODO: Add numeric separator tests when ESLint supports it.
+// Legacy octal literals
 ruleTester.run('number-literal-case', rule, {
+	valid: [
+		'const foo = 0777',
+		'const foo = 0888'
+	],
+	invalid: []
+});
+
+// TODO: Add numeric separator tests when ESLint supports it.
+const tests = {
 	valid: [
 		// Number
 		'const foo = 1234',
-		'const foo = 0777',
-		'const foo = 0888',
 		'const foo = 0b10',
 		'const foo = 0o1234567',
 		'const foo = 0xABCDEF',
@@ -81,6 +94,22 @@ ruleTester.run('number-literal-case', rule, {
 			errors: [error],
 			output: 'const foo = 0xABCDEFn'
 		},
+		// `0n`
+		{
+			code: 'const foo = 0B0n',
+			errors: [error],
+			output: 'const foo = 0b0n'
+		},
+		{
+			code: 'const foo = 0O0n',
+			errors: [error],
+			output: 'const foo = 0o0n'
+		},
+		{
+			code: 'const foo = 0X0n',
+			errors: [error],
+			output: 'const foo = 0x0n'
+		},
 
 		// Exponential notation
 		{
@@ -116,4 +145,8 @@ ruleTester.run('number-literal-case', rule, {
 			`
 		}
 	]
-});
+};
+
+ruleTester.run('number-literal-case', rule, tests);
+babelRuleTester.run('number-literal-case', rule, tests);
+typescriptRuleTester.run('number-literal-case', rule, tests);