-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
213 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
--- | ||
pageClass: "rule-details" | ||
sidebarDepth: 0 | ||
title: "regexp/sort-flags" | ||
description: "require regex flags to be sorted" | ||
--- | ||
# regexp/sort-flags | ||
|
||
> require regex flags to be sorted | ||
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge> | ||
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule. | ||
|
||
## :book: Rule Details | ||
|
||
The flags of JavaScript regular expressions should be sorted alphabetically | ||
because the flags of the `.flags` property of `RegExp` objects are always | ||
sorted. Not sorting flags in regex literals misleads readers into thinking that | ||
the order may have some purpose which it doesn't. | ||
|
||
<eslint-code-block fix> | ||
|
||
```js | ||
/* eslint regexp/sort-flags: "error" */ | ||
|
||
/* ✓ GOOD */ | ||
var foo = /abc/ | ||
var foo = /abc/iu | ||
var foo = /abc/gimsuy | ||
|
||
/* ✗ BAD */ | ||
var foo = /abc/mi | ||
var foo = /abc/us | ||
``` | ||
|
||
</eslint-code-block> | ||
|
||
## :wrench: Options | ||
|
||
Nothing. | ||
|
||
## :heart: Compatibility | ||
|
||
This rule was taken from [eslint-plugin-clean-regex]. | ||
This rule is compatible with [clean-regex/sort-flags] rule. | ||
|
||
[eslint-plugin-clean-regex]: https://github.com/RunDevelopment/eslint-plugin-clean-regex | ||
[clean-regex/sort-flags]: https://github.com/RunDevelopment/eslint-plugin-clean-regex/blob/master/docs/rules/sort-flags.md | ||
|
||
## :mag: Implementation | ||
|
||
- [Rule source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/lib/rules/sort-flags.ts) | ||
- [Test source](https://github.com/ota-meshi/eslint-plugin-regexp/blob/master/tests/lib/rules/sort-flags.ts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import type { Literal } from "estree" | ||
import type { RegExpVisitor } from "regexpp/visitor" | ||
import type { RegExpContext } from "../utils" | ||
import { createRule, defineRegexpVisitor } from "../utils" | ||
|
||
export default createRule("sort-flags", { | ||
meta: { | ||
docs: { | ||
description: "require regex flags to be sorted", | ||
// TODO Switch to recommended in the major version. | ||
// recommended: true, | ||
recommended: false, | ||
}, | ||
fixable: "code", | ||
schema: [], | ||
messages: { | ||
sortFlags: | ||
"The flags '{{flags}}' should in the order '{{sortedFlags}}'.", | ||
}, | ||
type: "suggestion", // "problem", | ||
}, | ||
create(context) { | ||
/** | ||
* Report | ||
*/ | ||
function report( | ||
node: Literal, | ||
flags: string, | ||
sortedFlags: string, | ||
flagsRange: [number, number], | ||
) { | ||
const sourceCode = context.getSourceCode() | ||
context.report({ | ||
node, | ||
loc: { | ||
start: sourceCode.getLocFromIndex(flagsRange[0]), | ||
end: sourceCode.getLocFromIndex(flagsRange[1]), | ||
}, | ||
messageId: "sortFlags", | ||
data: { flags, sortedFlags }, | ||
fix(fixer) { | ||
return fixer.replaceTextRange(flagsRange, sortedFlags) | ||
}, | ||
}) | ||
} | ||
|
||
/** | ||
* Sort regexp flags | ||
*/ | ||
function sortFlags(flagsStr: string): string { | ||
return [...flagsStr] | ||
.sort((a, b) => a.codePointAt(0)! - b.codePointAt(0)!) | ||
.join("") | ||
} | ||
|
||
/** | ||
* Create visitor | ||
*/ | ||
function createVisitor({ | ||
regexpNode, | ||
}: RegExpContext): RegExpVisitor.Handlers { | ||
if (regexpNode.type === "Literal") { | ||
const flags = regexpNode.regex.flags | ||
const sortedFlags = sortFlags(flags) | ||
if (flags !== sortedFlags) { | ||
report(regexpNode, flags, sortedFlags, [ | ||
regexpNode.range![1] - regexpNode.regex.flags.length, | ||
regexpNode.range![1], | ||
]) | ||
} | ||
} else { | ||
const flagsArg = regexpNode.arguments[1] | ||
if ( | ||
flagsArg.type === "Literal" && | ||
typeof flagsArg.value === "string" | ||
) { | ||
const flags = flagsArg.value | ||
const sortedFlags = sortFlags(flags) | ||
if (flags !== sortedFlags) { | ||
report(flagsArg, flags, sortedFlags, [ | ||
flagsArg.range![0] + 1, | ||
flagsArg.range![1] - 1, | ||
]) | ||
} | ||
} | ||
} | ||
|
||
return {} // not visit RegExpNodes | ||
} | ||
|
||
return defineRegexpVisitor(context, { | ||
createVisitor, | ||
}) | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { RuleTester } from "eslint" | ||
import rule from "../../../lib/rules/sort-flags" | ||
|
||
const tester = new RuleTester({ | ||
parserOptions: { | ||
ecmaVersion: 2020, | ||
sourceType: "module", | ||
}, | ||
}) | ||
|
||
tester.run("sort-flags", rule as any, { | ||
valid: [ | ||
String.raw`/\w/i`, | ||
String.raw`/\w/im`, | ||
String.raw`/\w/gi`, | ||
String.raw`/\w/gimsuy`, | ||
String.raw`new RegExp("\\w", "i")`, | ||
String.raw`new RegExp("\\w", "gi")`, | ||
String.raw`new RegExp("\\w", "gimsuy")`, | ||
String.raw`new RegExp("\\w", "dgimsuy")`, | ||
|
||
// ignore | ||
String.raw` | ||
const flags = "yusimg" | ||
new RegExp("\\w", flags) | ||
`, | ||
], | ||
invalid: [ | ||
{ | ||
code: String.raw`/\w/yusimg`, | ||
output: String.raw`/\w/gimsuy`, | ||
errors: [ | ||
{ | ||
message: "The flags 'yusimg' should in the order 'gimsuy'.", | ||
column: 5, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: String.raw`new RegExp("\\w", "yusimg")`, | ||
output: String.raw`new RegExp("\\w", "gimsuy")`, | ||
errors: [ | ||
{ | ||
message: "The flags 'yusimg' should in the order 'gimsuy'.", | ||
column: 20, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: String.raw`new RegExp("\\w", "yusimgd")`, | ||
output: String.raw`new RegExp("\\w", "dgimsuy")`, | ||
errors: [ | ||
{ | ||
message: | ||
"The flags 'yusimgd' should in the order 'dgimsuy'.", | ||
column: 20, | ||
}, | ||
], | ||
}, | ||
], | ||
}) |