11'use strict' ;
22const cleanRegexp = require ( 'clean-regexp' ) ;
3+ const { generate, optimize, parse} = require ( 'regexp-tree' ) ;
34const getDocumentationUrl = require ( './utils/get-documentation-url' ) ;
45const quoteString = require ( './utils/quote-string' ) ;
56
@@ -8,23 +9,46 @@ const message = 'Use regex shorthands to improve readability.';
89const create = context => {
910 return {
1011 'Literal[regex]' : node => {
11- const oldPattern = node . regex . pattern ;
12- const { flags} = node . regex ;
12+ const { type, value} = context . getSourceCode ( ) . getFirstToken ( node ) ;
1313
14- const newPattern = cleanRegexp ( oldPattern , flags ) ;
15-
16- // Handle regex literal inside RegExp constructor in the other handler
17- if ( node . parent . type === 'NewExpression' && node . parent . callee . name === 'RegExp' ) {
14+ if ( type !== 'RegularExpression' ) {
1815 return ;
1916 }
2017
21- if ( oldPattern !== newPattern ) {
18+ let parsedSource ;
19+ try {
20+ parsedSource = parse ( value ) ;
21+ } catch ( error ) {
2222 context . report ( {
2323 node,
24- message,
25- fix : fixer => fixer . replaceText ( node , `/${ newPattern } /${ flags } ` )
24+ message : '{{original}} can\'t be parsed: {{message}}' ,
25+ data : {
26+ original : value ,
27+ message : error . message
28+ }
2629 } ) ;
30+
31+ return ;
2732 }
33+
34+ const originalRegex = generate ( parsedSource ) . toString ( ) ;
35+ const optimizedRegex = optimize ( value ) . toString ( ) ;
36+
37+ if ( originalRegex === optimizedRegex ) {
38+ return ;
39+ }
40+
41+ context . report ( {
42+ node,
43+ message : '{{original}} can be optimized to {{optimized}}' ,
44+ data : {
45+ original : value ,
46+ optimized : optimizedRegex
47+ } ,
48+ fix ( fixer ) {
49+ return fixer . replaceText ( node , optimizedRegex ) ;
50+ }
51+ } ) ;
2852 } ,
2953 'NewExpression[callee.name="RegExp"]' : node => {
3054 const arguments_ = node . arguments ;
@@ -35,27 +59,18 @@ const create = context => {
3559
3660 const hasRegExp = arguments_ [ 0 ] . regex ;
3761
38- let oldPattern ;
39- let flags ;
4062 if ( hasRegExp ) {
41- oldPattern = arguments_ [ 0 ] . regex . pattern ;
42- flags = arguments_ [ 1 ] && arguments_ [ 1 ] . type === 'Literal' ? arguments_ [ 1 ] . value : arguments_ [ 0 ] . regex . flags ;
43- } else {
44- oldPattern = arguments_ [ 0 ] . value ;
45- flags = arguments_ [ 1 ] && arguments_ [ 1 ] . type === 'Literal' ? arguments_ [ 1 ] . value : '' ;
63+ return ;
4664 }
4765
66+ const oldPattern = arguments_ [ 0 ] . value ;
67+ const flags = arguments_ [ 1 ] && arguments_ [ 1 ] . type === 'Literal' ? arguments_ [ 1 ] . value : '' ;
68+
4869 const newPattern = cleanRegexp ( oldPattern , flags ) ;
4970
5071 if ( oldPattern !== newPattern ) {
51- let fixed ;
52- if ( hasRegExp ) {
53- fixed = `/${ newPattern } /` ;
54- } else {
55- // Escape backslash
56- fixed = ( newPattern || '' ) . replace ( / \\ / g, '\\\\' ) ;
57- fixed = quoteString ( fixed ) ;
58- }
72+ // Escape backslash
73+ const fixed = quoteString ( ( newPattern || '' ) . replace ( / \\ / g, '\\\\' ) ) ;
5974
6075 context . report ( {
6176 node,
0 commit comments