Skip to content

Commit d021a67

Browse files
committed
Merge branch 'master' into synonyms
# Conflicts: # tsdoc-config/src/TSDocConfigFile.ts
2 parents e605e3c + 4f3e575 commit d021a67

File tree

11 files changed

+722
-435
lines changed

11 files changed

+722
-435
lines changed

common/config/rush/pnpm-lock.yaml

Lines changed: 448 additions & 391 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eslint-plugin/CHANGELOG.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
{
22
"name": "eslint-plugin-tsdoc",
33
"entries": [
4+
{
5+
"version": "0.2.1",
6+
"tag": "eslint-plugin-tsdoc_v0.2.1",
7+
"date": "Tue, 21 Jan 2020 21:26:36 GMT",
8+
"comments": {
9+
"patch": [
10+
{
11+
"comment": "Use a cache to avoid repeatedly reloading tsdoc.json during linting"
12+
}
13+
],
14+
"dependency": [
15+
{
16+
"comment": "Updating dependency \"@microsoft/tsdoc-config\" from `0.12.16` to `0.13.0`"
17+
}
18+
]
19+
}
20+
},
421
{
522
"version": "0.2.0",
623
"tag": "eslint-plugin-tsdoc_v0.2.0",

eslint-plugin/CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Change Log - eslint-plugin-tsdoc
22

3-
This log was last generated on Tue, 19 Nov 2019 22:01:56 GMT and should not be manually modified.
3+
This log was last generated on Tue, 21 Jan 2020 21:26:36 GMT and should not be manually modified.
4+
5+
## 0.2.1
6+
Tue, 21 Jan 2020 21:26:36 GMT
7+
8+
### Patches
9+
10+
- Use a cache to avoid repeatedly reloading tsdoc.json during linting
411

512
## 0.2.0
613
Tue, 19 Nov 2019 22:01:56 GMT

eslint-plugin/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eslint-plugin-tsdoc",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"description": "An ESLint plugin that validates TypeScript doc comments",
55
"keywords": [
66
"TypeScript",
@@ -27,7 +27,7 @@
2727
},
2828
"dependencies": {
2929
"@microsoft/tsdoc": "0.12.16",
30-
"@microsoft/tsdoc-config": "0.12.16"
30+
"@microsoft/tsdoc-config": "0.13.0"
3131
},
3232
"devDependencies": {
3333
"@rushstack/eslint-config": "0.4.0",

eslint-plugin/src/ConfigCache.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
2+
import * as path from 'path';
3+
4+
import { Debug } from './Debug';
5+
6+
interface ICachedConfig {
7+
loadTimeMs: number;
8+
lastCheckTimeMs: number;
9+
configFile: TSDocConfigFile;
10+
}
11+
12+
// How often to check for modified input files. If a file's modification timestamp has changed, then we will
13+
// evict the cache entry immediately.
14+
const CACHE_CHECK_INTERVAL_MS: number = 3 * 1000;
15+
16+
// Evict old entries from the cache after this much time, regardless of whether the file was detected as being
17+
// modified or not.
18+
const CACHE_EXPIRE_MS: number = 20 * 1000;
19+
20+
// If this many objects accumulate in the cache, then it is cleared to avoid a memory leak.
21+
const CACHE_MAX_SIZE: number = 100;
22+
23+
export class ConfigCache {
24+
// findConfigPathForFolder() result --> loaded tsdoc.json configuration
25+
private static _cachedConfigs: Map<string, ICachedConfig> = new Map<string, ICachedConfig>();
26+
27+
/**
28+
* Node.js equivalent of performance.now().
29+
*/
30+
private static _getTimeInMs(): number {
31+
const [seconds, nanoseconds] = process.hrtime();
32+
return seconds * 1000 + nanoseconds / 1000000;
33+
}
34+
35+
public static getForSourceFile(sourceFilePath: string): TSDocConfigFile {
36+
const sourceFileFolder: string = path.dirname(path.resolve(sourceFilePath));
37+
38+
// First, determine the file to be loaded. If not found, the configFilePath will be an empty string.
39+
const configFilePath: string = TSDocConfigFile.findConfigPathForFolder(sourceFileFolder);
40+
41+
// If configFilePath is an empty string, then we'll use the folder of sourceFilePath as our cache key
42+
// (instead of an empty string)
43+
const cacheKey: string = configFilePath || (sourceFileFolder + '/');
44+
Debug.log(`Cache key: "${cacheKey}"`);
45+
46+
const nowMs: number = ConfigCache._getTimeInMs();
47+
48+
let cachedConfig: ICachedConfig | undefined = undefined;
49+
50+
// Do we have a cached object?
51+
cachedConfig = ConfigCache._cachedConfigs.get(cacheKey);
52+
53+
if (cachedConfig) {
54+
Debug.log('Cache hit');
55+
56+
// Is the cached object still valid?
57+
const loadAgeMs: number = nowMs - cachedConfig.loadTimeMs;
58+
const lastCheckAgeMs: number = nowMs - cachedConfig.lastCheckTimeMs;
59+
60+
if (loadAgeMs > CACHE_EXPIRE_MS || loadAgeMs < 0) {
61+
Debug.log('Evicting because item is expired');
62+
cachedConfig = undefined;
63+
ConfigCache._cachedConfigs.delete(cacheKey);
64+
} else if (lastCheckAgeMs > CACHE_CHECK_INTERVAL_MS || lastCheckAgeMs < 0) {
65+
Debug.log('Checking for modifications');
66+
cachedConfig.lastCheckTimeMs = nowMs;
67+
if (cachedConfig.configFile.checkForModifiedFiles()) {
68+
// Invalidate the cache because it failed to load completely
69+
Debug.log('Evicting because item was modified');
70+
cachedConfig = undefined;
71+
ConfigCache._cachedConfigs.delete(cacheKey);
72+
}
73+
}
74+
}
75+
76+
// Load the object
77+
if (!cachedConfig) {
78+
if (ConfigCache._cachedConfigs.size > CACHE_MAX_SIZE) {
79+
Debug.log('Clearing cache');
80+
ConfigCache._cachedConfigs.clear(); // avoid a memory leak
81+
}
82+
83+
const configFile: TSDocConfigFile = TSDocConfigFile.loadFile(configFilePath);
84+
85+
if (configFile.fileNotFound) {
86+
Debug.log(`File not found: "${configFilePath}"`);
87+
} else {
88+
Debug.log(`Loaded: "${configFilePath}"`);
89+
}
90+
91+
cachedConfig = {
92+
configFile,
93+
lastCheckTimeMs: nowMs,
94+
loadTimeMs: nowMs
95+
};
96+
97+
ConfigCache._cachedConfigs.set(cacheKey, cachedConfig);
98+
}
99+
100+
return cachedConfig.configFile;
101+
}
102+
}

eslint-plugin/src/Debug.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
export class Debug {
3+
// To debug the plugin, temporarily uncomment the body of this function
4+
public static log(message: string): void {
5+
// message = require("process").pid + ": " + message;
6+
// console.log(message);
7+
// require('fs').writeFileSync('C:\\Git\\log.txt', message + '\r\n', { flag: 'as' });
8+
}
9+
}

eslint-plugin/src/index.ts

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
1+
import * as eslint from "eslint";
2+
import * as ESTree from "estree";
23
import {
34
TSDocParser,
45
TextRange,
56
TSDocConfiguration,
67
ParserContext
78
} from "@microsoft/tsdoc";
8-
import {
9-
TSDocConfigFile
10-
} from '@microsoft/tsdoc-config';
11-
import * as eslint from "eslint";
12-
import * as ESTree from "estree";
9+
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
10+
11+
import { Debug } from './Debug';
12+
import { ConfigCache } from './ConfigCache';
1313

1414
const tsdocMessageIds: {[x: string]: string} = {};
1515

16-
const defaultTSDocConfiguration: TSDocConfiguration = new TSDocConfiguration()
16+
const defaultTSDocConfiguration: TSDocConfiguration = new TSDocConfiguration();
1717
defaultTSDocConfiguration.allTsdocMessageIds.forEach((messageId: string) => {
1818
tsdocMessageIds[messageId] = `${messageId}: {{unformattedText}}`;
1919
});
@@ -43,33 +43,44 @@ const plugin: IPlugin = {
4343
}
4444
},
4545
create: (context: eslint.Rule.RuleContext) => {
46-
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();
47-
4846
const sourceFilePath: string = context.getFilename();
49-
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(sourceFilePath);
47+
Debug.log(`Linting: "${sourceFilePath}"`);
5048

51-
if (!tsdocConfigFile.fileNotFound) {
52-
if (tsdocConfigFile.hasErrors) {
53-
context.report({
54-
loc: { line: 1, column: 1 },
55-
messageId: "error-loading-config-file",
56-
data: {
57-
details: tsdocConfigFile.getErrorSummary()
58-
}
59-
});
60-
}
49+
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration()
6150

62-
try {
63-
tsdocConfigFile.configureParser(tsdocConfiguration);
64-
} catch (e) {
65-
context.report({
66-
loc: { line: 1, column: 1 },
67-
messageId: "error-applying-config",
68-
data: {
69-
details: e.message
70-
}
71-
});
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+
}
63+
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+
}
7275
}
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+
});
7384
}
7485

7586
const tsdocParser: TSDocParser = new TSDocParser(tsdocConfiguration);

tsdoc-config/CHANGELOG.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
{
22
"name": "@microsoft/tsdoc-config",
33
"entries": [
4+
{
5+
"version": "0.13.0",
6+
"tag": "@microsoft/tsdoc-config_v0.13.0",
7+
"date": "Tue, 21 Jan 2020 21:26:36 GMT",
8+
"comments": {
9+
"minor": [
10+
{
11+
"comment": "Improve tsdoc.json parser to allow JSON comments"
12+
},
13+
{
14+
"comment": "Add a new API TSDocConfigFile.checkForModifiedFiles() to facilitate caching"
15+
}
16+
]
17+
}
18+
},
419
{
520
"version": "0.12.16",
621
"tag": "@microsoft/tsdoc-config_v0.12.16",

tsdoc-config/CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Change Log - @microsoft/tsdoc-config
22

3-
This log was last generated on Tue, 19 Nov 2019 22:01:56 GMT and should not be manually modified.
3+
This log was last generated on Tue, 21 Jan 2020 21:26:36 GMT and should not be manually modified.
4+
5+
## 0.13.0
6+
Tue, 21 Jan 2020 21:26:36 GMT
7+
8+
### Minor changes
9+
10+
- Improve tsdoc.json parser to allow JSON comments
11+
- Add a new API TSDocConfigFile.checkForModifiedFiles() to facilitate caching
412

513
## 0.12.16
614
Tue, 19 Nov 2019 22:01:56 GMT

tsdoc-config/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@microsoft/tsdoc-config",
3-
"version": "0.12.16",
3+
"version": "0.13.0",
44
"description": "A loader for the tsdoc.json file",
55
"keywords": [
66
"TypeScript",
@@ -22,11 +22,13 @@
2222
"dependencies": {
2323
"@microsoft/tsdoc": "0.12.16",
2424
"ajv": "~6.10.2",
25+
"jju": "~1.4.0",
2526
"resolve": "~1.12.0"
2627
},
2728
"devDependencies": {
2829
"@rushstack/eslint-config": "0.4.0",
2930
"@types/jest": "24.0.16",
31+
"@types/jju": "1.4.1",
3032
"@types/resolve": "0.0.8",
3133
"@types/node": "10.17.5",
3234
"eslint": "^6.0.0",

0 commit comments

Comments
 (0)