Skip to content

Commit 68895ff

Browse files
authored
build(awslint): Cache L1 constructs in the CFN resource linter. (#27290)
Incremental change to improve the performance of awslint. `CfnResourceReflection.findByName()` was checking the doc tags of every class in the assembly on each call, taking 170s for `aws-cdk-lib`. This change caches the tagged classes, eliminating the list traversal and taking `findByName` down to ~2s for the same package. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 6616026 commit 68895ff

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

packages/awslint/lib/rules/cfn-resource.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,29 @@ import { CoreTypes } from './core-types';
44
import { ResourceReflection } from './resource';
55
import { Linter } from '../linter';
66

7+
const cfnResourceTagName = 'cloudformationResource';
8+
79
// this linter verifies that we have L2 coverage. it finds all "Cfn" classes and verifies
810
// that we have a corresponding L1 class for it that's identified as a resource.
911
export const cfnResourceLinter = new Linter(a => CfnResourceReflection.findAll(a));
1012

13+
// Cache L1 constructs per type system.
14+
const l1ConstructCache = new Map<reflect.TypeSystem, Map<string, reflect.ClassType>>();
15+
16+
function cacheL1ConstructsForTypeSystem(sys: reflect.TypeSystem) {
17+
if (!l1ConstructCache.has(sys)) {
18+
l1ConstructCache.set(sys, new Map<string, reflect.ClassType>());
19+
20+
for (const cls of sys.classes) {
21+
const cfnResourceTag = cls.docs.customTag(cfnResourceTagName);
22+
23+
if (cfnResourceTag) {
24+
l1ConstructCache.get(sys)?.set(cfnResourceTag?.toLocaleLowerCase()!, cls);
25+
}
26+
}
27+
}
28+
}
29+
1130
cfnResourceLinter.add({
1231
code: 'resource-class',
1332
message: 'every resource must have a resource class (L2), add \'@resource %s\' to its docstring',
@@ -24,10 +43,13 @@ export class CfnResourceReflection {
2443
* @param fullName first two components are case-insensitive (e.g. `aws::s3::Bucket` is equivalent to `Aws::S3::Bucket`)
2544
*/
2645
public static findByName(sys: reflect.TypeSystem, fullName: string) {
27-
for (const cls of sys.classes) {
28-
if (cls.docs.customTag('cloudformationResource')?.toLocaleLowerCase() === fullName.toLocaleLowerCase()) {
29-
return new CfnResourceReflection(cls);
30-
}
46+
if (!l1ConstructCache.has(sys)) {
47+
cacheL1ConstructsForTypeSystem(sys);
48+
}
49+
50+
const cls = l1ConstructCache.get(sys)?.get(fullName.toLowerCase());
51+
if (cls) {
52+
return new CfnResourceReflection(cls);
3153
}
3254

3355
return undefined;

0 commit comments

Comments
 (0)