16
16
* limitations under the License.
17
17
*/
18
18
19
+ /* eslint-disable max-len, max-lines */
20
+
19
21
'use strict' ;
20
22
21
23
// MODULES //
@@ -43,14 +45,51 @@ var debug = logger( 'tsdoc-doctest' );
43
45
var RE_TSDOC = / \/ \* \* [ \s \S ] + ?\* \/ / g;
44
46
var RE_EXAMPLE = / @ e x a m p l e \s * ( [ \s \S ] * ?) (? = \n \s * @ \w | \* \/ | $ ) / g;
45
47
var RE_NEWLINE = / \r ? \n / g;
46
- var RE_ANNOTATION = / (?: \n | ^ ) (?: v a r | l e t | c o n s t ) ? ? ( [ a - z A - Z 0 - 9 . _ ] + ) ? = [ ^ ; ] * ? ; \n \/ \/ ? ( r e t u r n s | ( [ A - Z a - z ] [ A - Z a - z _ 0 - 9 ] * ) ? ? = > | t h r o w s ) { 0 , 1 } ( [ \s \S ] * ?) ( \n | $ ) / g;
48
+ var RE_ANNOTATION = / (?: \n | ^ ) (?: v a r | l e t | c o n s t ) ? ? ( [ a - z A - Z 0 - 9 . _ ] + ) ? = [ ^ ; ] * ; \n \/ \/ ? ( r e t u r n s | ( [ A - Z a - z ] [ A - Z a - z _ 0 - 9 ] * ) ? ? = > | t h r o w s ) ? ( [ \s \S ] * ?) ( \n | $ ) / g;
47
49
var RE_CONSOLE = / c o n s o l e \. (?: d i r | e r r o r | l o g ) / ;
48
50
var RE_COMMENT_PREFIX = / ^ \s * \* \s ? / gm;
51
+ var RE_SPECIAL_CHARS = / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g;
52
+ var regexCache = { } ;
53
+ var lineCountCache = { } ;
49
54
var rule ;
50
55
51
56
52
57
// FUNCTIONS //
53
58
59
+ /**
60
+ * Escapes special regex characters in a string.
61
+ *
62
+ * @private
63
+ * @param {string } str - string to escape
64
+ * @returns {string } escaped string
65
+ */
66
+ function escapeRegex ( str ) {
67
+ return str . replace ( RE_SPECIAL_CHARS , '\\$&' ) ;
68
+ }
69
+
70
+ /**
71
+ * Gets or creates a cached regex for finding return annotations.
72
+ *
73
+ * @private
74
+ * @param {string } annotationType - type of annotation (returns, throws, etc.)
75
+ * @param {string } value - expected value
76
+ * @returns {RegExp } compiled regular expression
77
+ */
78
+ function getAnnotationRegex ( annotationType , value ) {
79
+ var escapedValue ;
80
+ var pattern ;
81
+ var key ;
82
+
83
+ escapedValue = escapeRegex ( value ) ;
84
+ key = [ annotationType , escapedValue ] . join ( '::' ) ;
85
+
86
+ if ( ! regexCache [ key ] ) {
87
+ pattern = '// ' + annotationType + '\\s+' + escapedValue ;
88
+ regexCache [ key ] = new RegExp ( pattern ) ;
89
+ }
90
+ return regexCache [ key ] ;
91
+ }
92
+
54
93
/**
55
94
* Counts the number of lines in the given string.
56
95
*
@@ -59,7 +98,15 @@ var rule;
59
98
* @returns {number } number of lines
60
99
*/
61
100
function countLines ( str ) {
62
- return ( str . match ( RE_NEWLINE ) || '' ) . length ;
101
+ var matches ;
102
+
103
+ // Use cached result if available
104
+ if ( lineCountCache [ str ] ) {
105
+ return lineCountCache [ str ] ;
106
+ }
107
+ matches = str . match ( RE_NEWLINE ) ;
108
+ lineCountCache [ str ] = ( matches ) ? matches . length : 0 ;
109
+ return lineCountCache [ str ] ;
63
110
}
64
111
65
112
/**
@@ -78,7 +125,7 @@ function findName( scope, expected ) {
78
125
key = keys [ i ] ;
79
126
if (
80
127
! contains ( SCOPE_DEFAULTS , key ) &&
81
- ! compareValues ( scope [ key ] , expected )
128
+ compareValues ( scope [ key ] , expected ) === null
82
129
) {
83
130
return key ;
84
131
}
@@ -175,7 +222,7 @@ function processExampleCode( code, commentIdx, comments, scope, report, opts, so
175
222
commentStartIdx = sourceCode . text . indexOf ( comments [ commentIdx ] ) ;
176
223
177
224
// Find the annotation in the original comment
178
- returnAnnotationPattern = new RegExp ( '// ' + arr [ 2 ] + '\\s+' + arr [ 4 ] . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g , '\\$&' ) ) ;
225
+ returnAnnotationPattern = getAnnotationRegex ( arr [ 2 ] , arr [ 4 ] ) ;
179
226
annotationMatch = comments [ commentIdx ] . match ( returnAnnotationPattern ) ;
180
227
181
228
if ( ! annotationMatch ) {
@@ -281,9 +328,6 @@ function processExampleCode( code, commentIdx, comments, scope, report, opts, so
281
328
}
282
329
}
283
330
284
-
285
- // MAIN //
286
-
287
331
/**
288
332
* Rule for validating that return annotations in TypeScript declaration examples match the actual output.
289
333
*
@@ -357,6 +401,10 @@ function main( context ) {
357
401
var i ;
358
402
var j ;
359
403
404
+ // Clear caches to prevent memory leaks
405
+ regexCache = { } ;
406
+ lineCountCache = { } ;
407
+
360
408
// Resolve implementation path relative to TypeScript declaration file path:
361
409
implementationPath = options . implementationPath || '../../lib' ;
362
410
implPath = resolveImplementationPath ( filename , implementationPath ) ;
0 commit comments