`object-shorthand` with `ignoreConstructors` option wrongly identifies '_foo' as a constructor name
See original GitHub issueTell us about your environment
- ESLint Version: v5.16.0
- Node Version: v10.15.3
- npm Version: v6.4.1
What parser (default, Babel-ESLint, etc.) are you using?
default
Please show your full configuration:
Configuration
{
env: {
node: true
},
parserOptions: {
sourceType: 'script'
},
extends: [
'airbnb-base',
'plugin:eslint-comments/recommended'
],
rules: {
// Alterations of airbnb rules
'max-len': ['error', {
code: 105,
tabWidth: 4,
ignoreStrings: true,
ignoreTemplateLiterals: true,
ignoreRegExpLiterals: true,
ignoreUrls: true
}],
indent: ['error', 'tab'],
'no-tabs': ['error', {allowIndentationTabs: true}],
'comma-dangle': ['error', 'never'],
'object-curly-spacing': ['error', 'never'],
'one-var': ['off'],
'no-plusplus': ['off'],
'no-restricted-syntax': ['off'],
'no-param-reassign': ['off'],
'no-use-before-define': ['error', {functions: false}],
'object-curly-newline': ['error', {multiline: true, consistent: true}],
'one-var-declaration-per-line': ['error', 'initializations'],
'prefer-destructuring': ['error',
{
VariableDeclarator: {array: false, object: true},
AssignmentExpression: {array: false, object: false}
},
{enforceForRenamedProperties: false}
],
'no-invalid-this': ['error'],
'no-underscore-dangle': ['off'],
'space-before-function-paren': ['error', {
anonymous: 'never',
named: 'never',
asyncArrow: 'always'
}],
'func-names': ['off'],
'object-shorthand': ['error', 'always', {
avoidQuotes: true,
ignoreConstructors: true,
avoidExplicitReturnArrows: true
}],
// eslint-comments rules
'eslint-comments/no-unused-disable': ['error'],
'eslint-comments/disable-enable-pair': ['error', {allowWholeFile: true}]
}
}
What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.
const o = {
_foo: function() {
// Foo foo!
}
};
eslint lib/** --ext .js
What did you expect to happen?
Expected object-shorthand
rule to flag a violation of the rule. I am using ignoreConstructors: true
option but _foo
is not a constructor.
What actually happened? Please include the actual, raw output from ESLint.
No output. The rule is not triggered.
Are you willing to submit a pull request to fix this bug?
Yes.
However, I’m not completely sure what correct behavior is. What characters can a constructor name begin with?
The current check for if an identifier is a “constructor” here is:
function isConstructor(name) {
const firstChar = name.charAt(0);
return firstChar === firstChar.toUpperCase();
}
So '_foo'
is identified as a constructor. So is '$foo'
.
From ECMAScript spec here, it looks like '_'
and '$'
are the only non-letter characters which are legal as the start of identifiers, so the only chars which will cause this issue.
In which case, an additional line would solve it:
if (firstChar === '_' || firstChar === '$') return false;
But would _Foo
be considered a constructor name or not? $Foo
?
And are there any other unicode chars which should be similarly be considered not valid as first char of constructor names?
Certainly method names starting with _
are quite common cases, so it’d be good to solve that case at least.
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (7 by maintainers)
Thanks for swift reply. So are you saying that you think all the following should be treated as constructors names:
and these not:
If so, something like this would do it:
Good question, I can clarify that a bit if I expand on your example (demo):
This is a bit contrived, but the issue I see is that if we change the constructor-detection logic to be
firstChar !== "_" && firstChar !== "$" && firstChar === firstChar.toUpperCase()
, then_PrivateConstructor
wouldn’t be detected, and the error fromobject-shorthand
would be a false positive.Now that I typed out an example, what if instead of looking at
name.charAt(0)
, should we instead do the first non-/[_$]/
character? People could theoretically then run into the same issue you encountered with a name like_8Name
, but that seems way less common than an identifier with just a_
or$
prefix.