@@ -3,11 +3,12 @@ import { pseudoParameterDocsMap } from '../artifacts/PseudoParameterDocs';
33import { Context } from '../context/Context' ;
44import { IntrinsicFunction , PseudoParameter , PseudoParametersSet , TopLevelSection } from '../context/ContextType' ;
55import { getEntityMap } from '../context/SectionContextBuilder' ;
6- import { Mapping , Parameter , Resource } from '../context/semantic/Entity' ;
6+ import { Constant , Mapping , Parameter , Resource } from '../context/semantic/Entity' ;
77import { EntityType } from '../context/semantic/SemanticTypes' ;
88import { SyntaxTree } from '../context/syntaxtree/SyntaxTree' ;
99import { SyntaxTreeManager } from '../context/syntaxtree/SyntaxTreeManager' ;
1010import { DocumentManager } from '../document/DocumentManager' ;
11+ import { FeatureFlag } from '../featureFlag/FeatureFlagI' ;
1112import { SchemaRetriever } from '../schema/SchemaRetriever' ;
1213import { LoggerFactory } from '../telemetry/LoggerFactory' ;
1314import { Measure } from '../telemetry/TelemetryDecorator' ;
@@ -54,6 +55,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
5455 private readonly syntaxTreeManager : SyntaxTreeManager ,
5556 private readonly schemaRetriever : SchemaRetriever ,
5657 private readonly documentManager : DocumentManager ,
58+ private readonly constantsFeatureFlag : FeatureFlag ,
5759 ) { }
5860
5961 @Measure ( { name : 'getCompletions' } )
@@ -104,14 +106,19 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
104106 syntaxTree ,
105107 ) ;
106108
107- if ( ! parametersAndResourcesCompletions || parametersAndResourcesCompletions . length === 0 ) {
109+ const constantsCompletions = this . getConstantsCompletions ( syntaxTree ) ;
110+
111+ const allCompletions = [
112+ ...this . pseudoParameterCompletionItems ,
113+ ...( parametersAndResourcesCompletions ?? [ ] ) ,
114+ ...constantsCompletions ,
115+ ] ;
116+
117+ if ( allCompletions . length === this . pseudoParameterCompletionItems . length ) {
108118 return this . applyFuzzySearch ( this . pseudoParameterCompletionItems , context . text ) ;
109119 }
110120
111- return this . applyFuzzySearch (
112- [ ...this . pseudoParameterCompletionItems , ...parametersAndResourcesCompletions ] ,
113- context . text ,
114- ) ;
121+ return this . applyFuzzySearch ( allCompletions , context . text ) ;
115122 }
116123
117124 private handleSubArguments (
@@ -125,6 +132,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
125132 syntaxTree ,
126133 ) ;
127134 const getAttCompletions = this . getGetAttCompletions ( syntaxTree , context . logicalId ) ;
135+ const constantsCompletions = this . getConstantsCompletions ( syntaxTree , true ) ;
128136
129137 const baseItems = [ ...this . pseudoParameterCompletionItems ] ;
130138 if ( parametersAndResourcesCompletions && parametersAndResourcesCompletions . length > 0 ) {
@@ -133,6 +141,9 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
133141 if ( getAttCompletions . length > 0 ) {
134142 baseItems . push ( ...getAttCompletions ) ;
135143 }
144+ if ( constantsCompletions . length > 0 ) {
145+ baseItems . push ( ...constantsCompletions ) ;
146+ }
136147
137148 // Handle ${} parameter substitution context detection
138149 const subText = this . getTextForSub ( params . textDocument . uri , params . position , context ) ;
@@ -246,6 +257,50 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
246257 return completionItems ;
247258 }
248259
260+ private getConstantsAsCompletionItems (
261+ constantsMap : ReadonlyMap < string , Context > ,
262+ stringOnly : boolean = false ,
263+ ) : CompletionItem [ ] {
264+ const completionItems : CompletionItem [ ] = [ ] ;
265+ for ( const [ constantName , context ] of constantsMap ) {
266+ const constant = context . entity as Constant ;
267+
268+ if ( stringOnly && typeof constant . value !== 'string' ) {
269+ continue ;
270+ }
271+
272+ const valuePreview =
273+ typeof constant . value === 'string'
274+ ? constant . value
275+ : typeof constant . value === 'object'
276+ ? '[Object]'
277+ : String ( constant . value ) ;
278+
279+ completionItems . push (
280+ createCompletionItem ( `Const::${ constantName } ` , CompletionItemKind . Constant , {
281+ detail : `Constant` ,
282+ documentation : `Value: ${ valuePreview } ` ,
283+ insertText : `Const::${ constantName } ` ,
284+ } ) ,
285+ ) ;
286+ }
287+
288+ return completionItems ;
289+ }
290+
291+ private getConstantsCompletions ( syntaxTree : SyntaxTree , stringOnly : boolean = false ) : CompletionItem [ ] {
292+ if ( ! this . constantsFeatureFlag . isEnabled ( ) ) {
293+ return [ ] ;
294+ }
295+
296+ const constantsMap = getEntityMap ( syntaxTree , TopLevelSection . Constants ) ;
297+ if ( ! constantsMap || constantsMap . size === 0 ) {
298+ return [ ] ;
299+ }
300+
301+ return this . getConstantsAsCompletionItems ( constantsMap , stringOnly ) ;
302+ }
303+
249304 private shouldIncludeResourceCompletions ( context : Context ) : boolean {
250305 // Only provide resource completions in Resources and Outputs sections
251306 return context . section === TopLevelSection . Resources || context . section === TopLevelSection . Outputs ;
0 commit comments