Skip to content

Commit bdcd0ce

Browse files
committed
Improve enum usage
1 parent 8aee059 commit bdcd0ce

23 files changed

+153
-67
lines changed

eslint.config.mjs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,47 @@ export default tseslint.config([
116116
'promise/catch-or-return': 'off',
117117
},
118118
},
119+
{
120+
files: ['src/**'],
121+
rules: {
122+
'no-restricted-syntax': [
123+
'error',
124+
{
125+
selector: 'CallExpression[callee.property.name="logRecord"]',
126+
message:
127+
'Usage of logRecord() function is restricted in src code. This is meant for debugging purposes only',
128+
},
129+
{
130+
selector: 'MemberExpression[property.name="entityType"]',
131+
message:
132+
'Usage of entityType property is restricted in src code. This call is an expensive operations, use getEntityType from Context instead',
133+
},
134+
{
135+
selector:
136+
'Literal[value=/^(Resources|Parameters|Outputs|Mappings|Metadata|Rules|Conditions|Transform|AWSTemplateFormatVersion)$/]',
137+
message:
138+
'Usage of raw TopLevelSection strings is restricted in src code. Use TopLevelSection enum instead',
139+
},
140+
{
141+
selector:
142+
'Literal[value=/^(Output|Mapping|Metadata|Rule|Transform|AWSTemplateFormatVersion|ForEachResource)$/]',
143+
message: 'Usage of raw EntityType strings is restricted in src code. Use EntityType enum instead',
144+
},
145+
{
146+
selector:
147+
'Literal[value=/^AWS::(AccountId|Region|StackId|StackName|NotificationARNs|NoValue|Partition|URLSuffix)$/]',
148+
message:
149+
'Usage of raw PseudoParameter strings is restricted in src code. Use PseudoParameter enum instead',
150+
},
151+
{
152+
selector:
153+
'Literal[value=/^(CreationPolicy|DeletionPolicy|UpdatePolicy|UpdateReplacePolicy|DependsOn|Metadata)$/]',
154+
message:
155+
'Usage of raw ResourceAttribute strings is restricted in src code. Use ResourceAttribute enum instead',
156+
},
157+
],
158+
},
159+
},
119160
{
120161
files: ['tst/**'],
121162
plugins: {

src/autocomplete/CompletionRouter.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { CompletionParams } from 'vscode-languageserver';
22
import { Context } from '../context/Context';
33
import { ContextManager } from '../context/ContextManager';
4-
import { IntrinsicFunction, IntrinsicsUsingConditionKeyword, TopLevelSection } from '../context/ContextType';
4+
import {
5+
IntrinsicFunction,
6+
IntrinsicsUsingConditionKeyword,
7+
ResourceAttribute,
8+
TopLevelSection,
9+
} from '../context/ContextType';
510
import { isCondition } from '../context/ContextUtils';
611
import { Entity, Output, Parameter } from '../context/semantic/Entity';
712
import { EntityType } from '../context/semantic/SemanticTypes';
@@ -79,7 +84,7 @@ export class CompletionRouter implements SettingsConfigurable, Closeable {
7984
} else if (context.section === TopLevelSection.Resources) {
8085
provider = this.completionProviderMap.get(EntityType.Resource);
8186
} else if (context.atEntityKeyLevel()) {
82-
provider = this.entityFieldCompletionProviderMap.get(context.entity.entityType);
87+
provider = this.entityFieldCompletionProviderMap.get(context.getEntityType());
8388
}
8489

8590
const completions = provider?.getCompletions(context, params) ?? [];
@@ -137,12 +142,12 @@ export class CompletionRouter implements SettingsConfigurable, Closeable {
137142
}
138143

139144
// Resource UpdatePolicy Condition: ['Resources', 'LogicalId', 'UpdatePolicy', this.CONDITION]
140-
if (context.matchPathWithLogicalId(TopLevelSection.Resources, 'UpdatePolicy', Condition)) {
145+
if (context.matchPathWithLogicalId(TopLevelSection.Resources, ResourceAttribute.UpdatePolicy, Condition)) {
141146
return true;
142147
}
143148

144149
// Resource Metadata Condition: ['Resources', 'LogicalId', 'Metadata', this.CONDITION]
145-
if (context.matchPathWithLogicalId(TopLevelSection.Resources, 'Metadata', Condition)) {
150+
if (context.matchPathWithLogicalId(TopLevelSection.Resources, ResourceAttribute.Metadata, Condition)) {
146151
return true;
147152
}
148153

src/autocomplete/EntityFieldCompletionProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { FuzzySearchFunction, getFuzzySearchFunction } from '../utils/FuzzySearc
66
import { CompletionProvider } from './CompletionProvider';
77
import { createCompletionItem } from './CompletionUtils';
88

9+
/* eslint-disable no-restricted-syntax -- Entire class depends on Entity */
910
export class EntityFieldCompletionProvider<T extends Entity> implements CompletionProvider {
1011
public getCompletions(context: Context, _: CompletionParams): CompletionItem[] {
1112
const entity = context.entity as T;

src/autocomplete/IntrinsicFunctionArgumentCompletionProvider.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
310310
}
311311

312312
const resource = resourceContext.entity as Resource;
313-
if (!resource.Type || typeof resource.Type !== 'string') {
313+
if (!resource.Type) {
314314
continue;
315315
}
316316

@@ -601,7 +601,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
601601
private getMappingEntity(mappingsEntities: Map<string, Context>, mappingName: string): Mapping | undefined {
602602
try {
603603
const mappingContext = mappingsEntities.get(mappingName);
604-
if (!mappingContext?.entity || mappingContext.entity.entityType !== EntityType.Mapping) {
604+
if (!mappingContext || mappingContext.getEntityType() !== EntityType.Mapping) {
605605
return undefined;
606606
}
607607
return mappingContext.entity as Mapping;
@@ -655,13 +655,13 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
655655
}
656656

657657
const resourceContext = resourceEntities.get(resourceLogicalId);
658-
if (!resourceContext?.entity || resourceContext.entity.entityType !== EntityType.Resource) {
658+
if (!resourceContext || resourceContext.getEntityType() !== EntityType.Resource) {
659659
return undefined;
660660
}
661661

662662
const resource = resourceContext.entity as Resource;
663663
const resourceType = resource.Type;
664-
if (!resourceType || typeof resourceType !== 'string') {
664+
if (!resourceType) {
665665
return undefined;
666666
}
667667

src/context/Context.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,22 @@ import {
55
IntrinsicsSet,
66
PseudoParametersSet,
77
ResourceAttributesSet,
8+
SectionType,
89
TopLevelSection,
910
TopLevelSectionsSet,
1011
TopLevelSectionsWithLogicalIdsSet,
1112
} from './ContextType';
1213
import { IntrinsicContext } from './IntrinsicContext';
1314
import { Entity } from './semantic/Entity';
14-
import { nodeToEntity } from './semantic/EntityBuilder';
15+
import { entityTypeFromSection, nodeToEntity } from './semantic/EntityBuilder';
1516
import { normalizeIntrinsicFunction } from './semantic/Intrinsics';
17+
import { EntityType } from './semantic/SemanticTypes';
1618
import { PropertyPath } from './syntaxtree/SyntaxTree';
1719
import { NodeType } from './syntaxtree/utils/NodeType';
1820
import { YamlNodeTypes, CommonNodeTypes } from './syntaxtree/utils/TreeSitterTypes';
1921
import { TransformContext } from './TransformContext';
2022

21-
export type SectionType = TopLevelSection | 'Unknown';
22-
export type QuoteCharacter = '"' | "'";
23+
type QuoteCharacter = '"' | "'";
2324

2425
export class Context {
2526
public readonly section: SectionType;
@@ -64,6 +65,10 @@ export class Context {
6465
return this._entity;
6566
}
6667

68+
public getEntityType(): EntityType {
69+
return entityTypeFromSection(this.section, this.logicalId);
70+
}
71+
6772
public get intrinsicContext(): IntrinsicContext {
6873
this._intrinsicContext ??= new IntrinsicContext(this.pathToRoot, this.documentType);
6974
return this._intrinsicContext;
@@ -310,7 +315,7 @@ export class Context {
310315
return undefined;
311316
}
312317

313-
public record() {
318+
public logRecord() {
314319
return {
315320
section: this.section,
316321
logicalId: this.logicalId,
@@ -322,7 +327,7 @@ export class Context {
322327
node: { start: this.node.startPosition, end: this.node.endPosition },
323328
root: { start: this.entityRootNode?.startPosition, end: this.entityRootNode?.endPosition },
324329
entity: this.entity,
325-
intrinsicContext: this.intrinsicContext.record(),
330+
intrinsicContext: this.intrinsicContext.logRecord(), // eslint-disable-line no-restricted-syntax
326331
isKey: this.isKey(),
327332
isValue: this.isValue(),
328333
};

src/context/ContextType.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-restricted-syntax -- enum definitions */
12
export enum TopLevelSection {
23
Resources = 'Resources',
34
Parameters = 'Parameters',
@@ -11,6 +12,8 @@ export enum TopLevelSection {
1112
Description = 'Description',
1213
}
1314

15+
export type SectionType = TopLevelSection | 'Unknown';
16+
1417
export enum IntrinsicFunction {
1518
Base64 = 'Fn::Base64',
1619
Cidr = 'Fn::Cidr',

src/context/ContextWithRelatedEntities.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SyntaxNode } from 'tree-sitter';
22
import { DocumentType } from '../document/Document';
3-
import { Context, SectionType, logicalIdAndSection } from './Context';
4-
import { TopLevelSection, TopLevelSectionsWithLogicalIdsSet } from './ContextType';
3+
import { Context, logicalIdAndSection } from './Context';
4+
import { SectionType, TopLevelSection, TopLevelSectionsWithLogicalIdsSet } from './ContextType';
55
import { contextEntitiesInSections } from './SectionContextBuilder';
66
import { Entity } from './semantic/Entity';
77
import { referencedLogicalIds, selectText } from './semantic/LogicalIdReferenceFinder';
@@ -29,9 +29,9 @@ export class ContextWithRelatedEntities extends Context {
2929
return this._relatedEntities;
3030
}
3131

32-
override record() {
32+
override logRecord() {
3333
return {
34-
...super.record(),
34+
...super.logRecord(), // eslint-disable-line no-restricted-syntax
3535
relatedEntities: this.transformNestedMap(this.relatedEntities),
3636
};
3737
}

src/context/FileContext.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class FileContext {
8282

8383
try {
8484
if (section === TopLevelSection.Transform) {
85-
return [createEntityFromObject('Transform', parseObject(parsedData, this.documentType), section)];
85+
return [createEntityFromObject('Unknown', parseObject(parsedData, this.documentType), section)];
8686
}
8787

8888
if (typeof parsedData !== 'object') return [];

src/context/IntrinsicContext.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ export class IntrinsicContext {
8989
return IntrinsicsSet.has(normalized) ? (normalized as IntrinsicFunction) : undefined;
9090
}
9191

92-
public record() {
92+
public logRecord() {
9393
const intrinsicFunction = this.intrinsicFunction();
9494
return {
9595
isInsideIntrinsic: intrinsicFunction !== undefined,
96-
intrinsicFunction: intrinsicFunction?.record(),
96+
intrinsicFunction: intrinsicFunction?.logRecord(), // eslint-disable-line no-restricted-syntax
9797
};
9898
}
9999
}
@@ -208,7 +208,7 @@ class IntrinsicFunctionInfo {
208208
set.add(text.split('.')[0].trim());
209209
}
210210

211-
public record() {
211+
public logRecord() {
212212
return {
213213
type: this.type,
214214
args: this.args,

src/context/SectionContextBuilder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { SyntaxNode } from 'tree-sitter';
22
import { DocumentType } from '../document/Document';
33
import { LoggerFactory } from '../telemetry/LoggerFactory';
4-
import { Context, SectionType } from './Context';
5-
import { TopLevelSection, TopLevelSectionsWithLogicalIdsSet } from './ContextType';
4+
import { Context } from './Context';
5+
import { SectionType, TopLevelSection, TopLevelSectionsWithLogicalIdsSet } from './ContextType';
66
import { SyntaxTree } from './syntaxtree/SyntaxTree';
77
import { NodeType } from './syntaxtree/utils/NodeType';
88
import { FieldNames, YamlNodeTypes } from './syntaxtree/utils/TreeSitterTypes';

0 commit comments

Comments
 (0)