1
-
1
+ import * as eslint from "eslint" ;
2
+ import * as ESTree from "estree" ;
2
3
import {
3
4
TSDocParser ,
4
5
TextRange ,
5
6
TSDocConfiguration ,
6
7
ParserContext
7
8
} from "@microsoft/tsdoc" ;
8
- import {
9
- TSDocConfigFile
10
- } from '@microsoft/tsdoc-config' ;
11
- import * as eslint from "eslint" ;
12
- import * as ESTree from "estree" ;
13
- import * as path from 'path' ;
9
+ import { TSDocConfigFile } from '@microsoft/tsdoc-config' ;
10
+
11
+ import { Debug } from './Debug' ;
12
+ import { ConfigCache } from './ConfigCache' ;
14
13
15
14
const tsdocMessageIds : { [ x : string ] : string } = { } ;
16
15
@@ -23,33 +22,6 @@ interface IPlugin {
23
22
rules : { [ x : string ] : eslint . Rule . RuleModule } ;
24
23
}
25
24
26
- // To debug the plugin, temporarily uncomment the body of this function
27
- function debug ( message : string ) : void {
28
- message = require ( "process" ) . pid + ": " + message ;
29
- console . log ( message ) ;
30
- require ( 'fs' ) . writeFileSync ( 'C:\\Git\\log.txt' , message + '\r\n' , { flag : 'as' } ) ;
31
- }
32
-
33
- interface ICachedConfig {
34
- loadTimeMs : number ;
35
- lastCheckTimeMs : number ;
36
- configFile : TSDocConfigFile ;
37
- }
38
-
39
- // How often to check for modified input files. If a file's modification timestamp has changed, then we will
40
- // evict the cache entry immediately.
41
- const CACHE_CHECK_INTERVAL_MS : number = 15 * 1000 ;
42
-
43
- // Evict old entries from the cache after this much time, regardless of whether the file was detected as being
44
- // modified or not.
45
- const CACHE_EXPIRE_MS : number = 30 * 1000 ;
46
-
47
- // If this many objects accumulate in the cache, then it is cleared to avoid a memory leak.
48
- const CACHE_MAX_SIZE : number = 100 ;
49
-
50
- // findConfigPathForFolder() result --> loaded tsdoc.json configuration
51
- const cachedConfigs : Map < string , ICachedConfig > = new Map < string , ICachedConfig > ( ) ;
52
-
53
25
const plugin : IPlugin = {
54
26
rules : {
55
27
// NOTE: The actual ESLint rule name will be "tsdoc/syntax". It is calculated by deleting "eslint-plugin-"
@@ -72,89 +44,43 @@ const plugin: IPlugin = {
72
44
} ,
73
45
create : ( context : eslint . Rule . RuleContext ) => {
74
46
const sourceFilePath : string = context . getFilename ( ) ;
47
+ Debug . log ( `Linting: "${ sourceFilePath } "` ) ;
75
48
76
- debug ( `Linting: "${ sourceFilePath } "` ) ;
77
-
78
- // First, determine the file to be loaded. If not found, the configFilePath will be an empty string.
79
- const configFilePath : string = '' ; // TSDocConfigFile.findConfigPathForFolder(sourceFilePath);
80
-
81
- // If configFilePath is an empty string, then we'll use the folder of sourceFilePath as our cache key
82
- // (instead of an empty string)
83
- const cacheKey : string = configFilePath || path . dirname ( sourceFilePath ) ;
84
- debug ( `Cache key: "${ cacheKey } "` ) ;
85
-
86
- const nowMs : number = ( new Date ( ) ) . getTime ( ) ;
87
-
88
- let cachedConfig : ICachedConfig | undefined = undefined ;
89
-
90
- // Do we have a cached object?
91
- cachedConfig = cachedConfigs . get ( cacheKey ) ;
92
-
93
- if ( cachedConfig ) {
94
- debug ( 'Cache hit' ) ;
95
-
96
- // Is the cached object still valid?
97
- const loadAgeMs : number = nowMs - cachedConfig . loadTimeMs ;
98
- const lastCheckAgeMs : number = nowMs - cachedConfig . lastCheckTimeMs ;
99
-
100
- if ( loadAgeMs > CACHE_EXPIRE_MS || loadAgeMs < 0 ) {
101
- debug ( 'Evicting because item is expired' ) ;
102
- cachedConfig = undefined ;
103
- cachedConfigs . delete ( cacheKey ) ;
104
- } else if ( lastCheckAgeMs > CACHE_CHECK_INTERVAL_MS || lastCheckAgeMs < 0 ) {
105
- debug ( 'Checking for modifications' ) ;
106
- cachedConfig . lastCheckTimeMs = nowMs ;
107
- if ( cachedConfig . configFile . checkForModifiedFiles ( ) ) {
108
- // Invalidate the cache because it failed to load completely
109
- debug ( 'Evicting because item was modified' ) ;
110
- cachedConfig = undefined ;
111
- cachedConfigs . delete ( cacheKey ) ;
112
- }
113
- }
114
- }
115
-
116
- // Load the object
117
- if ( ! cachedConfig ) {
118
- if ( cachedConfigs . size > CACHE_MAX_SIZE ) {
119
- debug ( 'Clearing cache' ) ;
120
- cachedConfigs . clear ( ) ; // avoid a memory leak
121
- }
122
-
123
- debug ( `LOADING CONFIG: ${ configFilePath } ` ) ;
124
- cachedConfig = {
125
- configFile : TSDocConfigFile . loadFile ( configFilePath ) ,
126
- lastCheckTimeMs : nowMs ,
127
- loadTimeMs : nowMs
128
- } ;
129
-
130
- cachedConfigs . set ( cacheKey , cachedConfig ) ;
131
- }
132
-
133
- const tsdocConfigFile : TSDocConfigFile = cachedConfig . configFile ;
134
49
const tsdocConfiguration : TSDocConfiguration = new TSDocConfiguration ( )
135
50
136
- if ( ! tsdocConfigFile . fileNotFound ) {
137
- if ( tsdocConfigFile . hasErrors ) {
138
- context . report ( {
139
- loc : { line : 1 , column : 1 } ,
140
- messageId : "error-loading-config-file" ,
141
- data : {
142
- details : tsdocConfigFile . getErrorSummary ( )
143
- }
144
- } ) ;
145
- }
51
+ try {
52
+ const tsdocConfigFile : TSDocConfigFile = ConfigCache . getForSourceFile ( sourceFilePath ) ;
53
+ if ( ! tsdocConfigFile . fileNotFound ) {
54
+ if ( tsdocConfigFile . hasErrors ) {
55
+ context . report ( {
56
+ loc : { line : 1 , column : 1 } ,
57
+ messageId : "error-loading-config-file" ,
58
+ data : {
59
+ details : tsdocConfigFile . getErrorSummary ( )
60
+ }
61
+ } ) ;
62
+ }
146
63
147
- try {
148
- tsdocConfigFile . configureParser ( tsdocConfiguration ) ;
149
- } catch ( e ) {
150
- context . report ( {
151
- loc : { line : 1 , column : 1 } ,
152
- messageId : "error-applying-config" ,
153
- data : {
154
- details : e . message
155
- }
156
- } ) ;
64
+ try {
65
+ tsdocConfigFile . configureParser ( tsdocConfiguration ) ;
66
+ } catch ( e ) {
67
+ context . report ( {
68
+ loc : { line : 1 , column : 1 } ,
69
+ messageId : "error-applying-config" ,
70
+ data : {
71
+ details : e . message
72
+ }
73
+ } ) ;
74
+ }
157
75
}
76
+ } catch ( e ) {
77
+ context . report ( {
78
+ loc : { line : 1 , column : 1 } ,
79
+ messageId : "error-loading-config-file" ,
80
+ data : {
81
+ details : `Unexpected exception: ${ e . message } `
82
+ }
83
+ } ) ;
158
84
}
159
85
160
86
const tsdocParser : TSDocParser = new TSDocParser ( tsdocConfiguration ) ;
0 commit comments