Skip to content

Commit

Permalink
enable sonar/inconsistent-function-call
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Aug 13, 2024
1 parent 0d8fe67 commit b35e68e
Show file tree
Hide file tree
Showing 20 changed files with 46 additions and 25 deletions.
30 changes: 17 additions & 13 deletions packages/core-js-compat/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@
// eslint-disable-next-line es/no-object-hasown -- safe
const has = Object.hasOwn || Function.call.bind({}.hasOwnProperty);

function semver(input) {
if (input instanceof semver) return input;
// eslint-disable-next-line new-cap -- ok
if (!(this instanceof semver)) return new semver(input);
const match = /(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(input);
if (!match) throw new TypeError(`Invalid version: ${ input }`);
const [, $major, $minor, $patch] = match;
this.major = +$major;
this.minor = $minor ? +$minor : 0;
this.patch = $patch ? +$patch : 0;
const VERSION_PATTERN = /(\d+)(?:\.(\d+))?(?:\.(\d+))?/;

class SemVer {
constructor(input) {
const match = VERSION_PATTERN.exec(input);
if (!match) throw new TypeError(`Invalid version: ${ input }`);
const [, $major, $minor, $patch] = match;
this.major = +$major;
this.minor = $minor ? +$minor : 0;
this.patch = $patch ? +$patch : 0;
}
toString() {
return `${ this.major }.${ this.minor }.${ this.patch }`;
}
}

semver.prototype.toString = function () {
return `${ this.major }.${ this.minor }.${ this.patch }`;
};
function semver(input) {
return input instanceof SemVer ? input : new SemVer(input);
}

function compare($a, operator, $b) {
const a = semver($a);
Expand Down
4 changes: 2 additions & 2 deletions packages/core-js/internals/array-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ if (!NATIVE_ARRAY_BUFFER) {
});
} else {
var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME && NativeArrayBuffer.name !== ARRAY_BUFFER;
/* eslint-disable no-new -- required for testing */
/* eslint-disable no-new, sonar/inconsistent-function-call -- required for testing */
if (!fails(function () {
NativeArrayBuffer(1);
}) || !fails(function () {
Expand All @@ -216,7 +216,7 @@ if (!NATIVE_ARRAY_BUFFER) {
new NativeArrayBuffer(NaN);
return NativeArrayBuffer.length !== 1 || INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;
})) {
/* eslint-enable no-new -- required for testing */
/* eslint-enable no-new, sonar/inconsistent-function-call -- required for testing */
$ArrayBuffer = function ArrayBuffer(length) {
anInstance(this, ArrayBufferPrototype);
return inheritIfRequired(new NativeArrayBuffer(toIndex(length)), this, $ArrayBuffer);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
/* eslint-disable no-new -- required for testing */
/* eslint-disable no-new, sonar/inconsistent-function-call -- required for testing */
var globalThis = require('../internals/global-this');
var fails = require('../internals/fails');
var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/modules/es.regexp.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var BASE_FORCED = DESCRIPTORS &&
(!CORRECT_NEW || MISSED_STICKY || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG || fails(function () {
re2[MATCH] = false;
// RegExp constructor can alter flags and IsRegExp works correct with @@match
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
return NativeRegExp(re1) !== re1 || NativeRegExp(re2) === re2 || String(NativeRegExp(re1, 'i')) !== '/a/i';
}));

Expand Down
1 change: 1 addition & 0 deletions packages/core-js/modules/es.symbol.description.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ if (DESCRIPTORS && isCallable(NativeSymbol) && (!('description' in SymbolPrototy
var SymbolWrapper = function Symbol() {
var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString(arguments[0]);
var result = isPrototypeOf(SymbolPrototype, this)
// eslint-disable-next-line sonar/inconsistent-function-call -- ok
? new NativeSymbol(description)
// in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
: description === undefined ? NativeSymbol() : NativeSymbol(description);
Expand Down
2 changes: 2 additions & 0 deletions tests/eslint/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,8 @@ const base = {
'sonar/expression-complexity': [OFF, { max: 3 }],
// `in` should not be used with primitive types
'sonar/in-operator-type-error': ERROR,
// functions should be called consistently with or without `new`
'sonar/inconsistent-function-call': ERROR,

// sonarjs
// collection sizes and array length comparisons should make sense
Expand Down
1 change: 1 addition & 0 deletions tests/unit-global/es.error.cause.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable sonar/inconsistent-function-call -- required for testing */
import { GLOBAL, PROTO } from '../helpers/constants.js';

const { create } = Object;
Expand Down
1 change: 1 addition & 0 deletions tests/unit-global/es.typed-array.constructors.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ if (DESCRIPTORS) {
assert.throws(() => new TypedArray(new ArrayBuffer(8), 16), 'If newByteLength < 0, throw a RangeError exception');
assert.throws(() => new TypedArray(new ArrayBuffer(24), 8, 24), 'If offset+newByteLength > bufferByteLength, throw a RangeError exception');
}
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => TypedArray(1), TypeError, 'throws without `new`');
assert.same(TypedArray[Symbol.species], TypedArray, '@@species');
});
Expand Down
2 changes: 1 addition & 1 deletion tests/unit-pure/es.aggregate-error.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable unicorn/throw-new-error -- testing */
/* eslint-disable unicorn/throw-new-error, sonar/inconsistent-function-call -- required for testing */
import AggregateError from 'core-js-pure/es/aggregate-error';
import Symbol from 'core-js-pure/es/symbol';
import toString from 'core-js-pure/es/object/to-string';
Expand Down
1 change: 1 addition & 0 deletions tests/unit-pure/es.error.cause.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable sonar/inconsistent-function-call -- required for testing */
import { PROTO } from '../helpers/constants.js';

import path from 'core-js-pure/es/error';
Expand Down
1 change: 1 addition & 0 deletions tests/unit-pure/es.number.constructor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable sonar/inconsistent-function-call -- required for testing */
import globalThis from 'core-js-pure/es/global-this';
import create from 'core-js-pure/es/object/create';
import Number from 'core-js-pure/es/number';
Expand Down
7 changes: 4 additions & 3 deletions tests/unit-pure/es.promise.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import create from 'core-js-pure/es/object/create';

QUnit.test('Promise', assert => {
assert.isFunction(Promise);
assert.throws(() => {
Promise();
}, 'throws w/o `new`');
new Promise(function (resolve, reject) {
assert.isFunction(resolve, 'resolver is function');
assert.isFunction(reject, 'rejector is function');
if (STRICT) assert.same(this, undefined, 'correct executor context');
});
assert.throws(() => {
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
Promise();
}, 'throws w/o `new`');
});

if (DESCRIPTORS) QUnit.test('Promise operations order', assert => {
Expand Down
5 changes: 3 additions & 2 deletions tests/unit-pure/esnext.async-disposable-stack.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ QUnit.test('AsyncDisposableStack constructor', assert => {
assert.isFunction(AsyncDisposableStack);
assert.arity(AsyncDisposableStack, 0);
assert.name(AsyncDisposableStack, 'AsyncDisposableStack');

assert.throws(() => AsyncDisposableStack(), 'throws w/o `new`');
assert.true(new AsyncDisposableStack() instanceof AsyncDisposableStack);

assert.same(AsyncDisposableStack.prototype.constructor, AsyncDisposableStack);

// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => AsyncDisposableStack(), 'throws w/o `new`');
});

QUnit.test('AsyncDisposableStack#disposeAsync', assert => {
Expand Down
1 change: 1 addition & 0 deletions tests/unit-pure/esnext.async-iterator.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ QUnit.test('AsyncIterator', assert => {
}

assert.throws(() => new AsyncIterator(), 'direct constructor throws');
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => AsyncIterator(), 'throws w/o `new`');
});

Expand Down
4 changes: 3 additions & 1 deletion tests/unit-pure/esnext.disposable-stack.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ QUnit.test('DisposableStack constructor', assert => {
assert.arity(DisposableStack, 0);
assert.name(DisposableStack, 'DisposableStack');

assert.throws(() => DisposableStack(), 'throws w/o `new`');
assert.true(new DisposableStack() instanceof DisposableStack);

assert.same(DisposableStack.prototype.constructor, DisposableStack);

// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => DisposableStack(), 'throws w/o `new`');
});

QUnit.test('DisposableStack#dispose', assert => {
Expand Down
1 change: 1 addition & 0 deletions tests/unit-pure/esnext.iterator.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ QUnit.test('Iterator', assert => {
}

assert.throws(() => new Iterator(), 'direct constructor throws');
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => Iterator(), 'throws w/o `new`');
});

Expand Down
3 changes: 2 additions & 1 deletion tests/unit-pure/esnext.observable.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Observable from 'core-js-pure/full/observable';
QUnit.test('Observable', assert => {
assert.isFunction(Observable);
assert.arity(Observable, 1);
assert.throws(() => Observable(() => { /* empty */ }), 'throws w/o `new`');
const observable = new Observable(function (subscriptionObserver) {
assert.same(typeof subscriptionObserver, 'object', 'Subscription observer is object');
assert.same(subscriptionObserver.constructor, Object);
Expand All @@ -23,6 +22,8 @@ QUnit.test('Observable', assert => {
});
observable.subscribe({});
assert.true(observable instanceof Observable);
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => Observable(() => { /* empty */ }), 'throws w/o `new`');
});

QUnit.test('Observable#subscribe', assert => {
Expand Down
2 changes: 1 addition & 1 deletion tests/unit-pure/esnext.suppressed-error.constructor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable unicorn/throw-new-error -- testing */
/* eslint-disable unicorn/throw-new-error, sonar/inconsistent-function-call -- testing */
import SuppressedError from 'core-js-pure/actual/suppressed-error';
import Symbol from 'core-js-pure/es/symbol';
import toString from 'core-js-pure/es/object/to-string';
Expand Down
1 change: 1 addition & 0 deletions tests/unit-pure/web.dom-exception.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ QUnit.test('DOMException', assert => {
assert.same(DOMException.prototype[errors[name].s], errors[name].c, `DOMException.prototype.${ errors[name].s }`);
}

// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
assert.throws(() => DOMException(42, 'DataCloneError'), "DOMException(42, 'DataCloneError')");
const symbol = Symbol('DOMException constructor test');
assert.throws(() => new DOMException(symbol, 'DataCloneError'), "new DOMException(Symbol(), 'DataCloneError')");
Expand Down
1 change: 1 addition & 0 deletions tests/unit-pure/web.url-search-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ QUnit.test('URLSearchParams', assert => {

// https://github.com/oven-sh/bun/issues/9253
if (!BUN) assert.throws(() => {
// eslint-disable-next-line sonar/inconsistent-function-call -- required for testing
URLSearchParams('');
}, 'throws w/o `new`');

Expand Down

0 comments on commit b35e68e

Please sign in to comment.