1+ /**
2+ * Copyright IBM Corp. 2025
3+ * Assisted by CursorAI
4+ */
5+
16import * as vscode from 'vscode' ;
27import { getRootOperationsMap } from '../utils/stepzenProjectScanner' ;
8+ import { services } from '../services' ;
9+ import { handleError } from '../errors' ;
310
411/**
512 * Adds a @materializer directive to a GraphQL field
@@ -9,84 +16,101 @@ import { getRootOperationsMap } from '../utils/stepzenProjectScanner';
916 * @returns Promise that resolves when the materializer has been added or operation is cancelled
1017 */
1118export async function addMaterializer ( ) {
12- const editor = vscode . window . activeTextEditor ;
13- if ( ! editor ) {
14- vscode . window . showErrorMessage ( 'No active editor' ) ;
15- return ;
16- }
19+ try {
20+ services . logger . info ( "Starting Add Materializer command" ) ;
21+
22+ const editor = vscode . window . activeTextEditor ;
23+ if ( ! editor ) {
24+ vscode . window . showErrorMessage ( 'No active editor' ) ;
25+ services . logger . warn ( "Add Materializer failed: No active editor" ) ;
26+ return ;
27+ }
1728
18- const document = editor . document ;
19- const position = editor . selection . active ;
20- const line = document . lineAt ( position . line ) ;
21- const lineText = line . text ;
29+ const document = editor . document ;
30+ const position = editor . selection . active ;
31+ const line = document . lineAt ( position . line ) ;
32+ const lineText = line . text ;
2233
23- // Determine current indentation from the line to preserve formatting
24- const baseIndent = lineText . substring ( 0 , line . firstNonWhitespaceCharacterIndex ) ;
34+ // Determine current indentation from the line to preserve formatting
35+ const baseIndent = lineText . substring ( 0 , line . firstNonWhitespaceCharacterIndex ) ;
2536
26- // Extract field name and declared type from the current line
27- const trimmed = lineText . trim ( ) ;
28- const fieldMatch = trimmed . match ( / ^ ( \w + ) \s * : \s * ( [ ^ \s ] + ) / ) ;
29- if ( ! fieldMatch ) {
30- vscode . window . showInformationMessage ( 'Place cursor on a GraphQL field definition.' ) ;
31- return ;
32- }
33- const declaredType = fieldMatch [ 2 ] ;
37+ // Extract field name and declared type from the current line
38+ const trimmed = lineText . trim ( ) ;
39+ const fieldMatch = trimmed . match ( / ^ ( \w + ) \s * : \s * ( [ ^ \s ] + ) / ) ;
40+ if ( ! fieldMatch ) {
41+ vscode . window . showInformationMessage ( 'Place cursor on a GraphQL field definition.' ) ;
42+ services . logger . warn ( "Add Materializer failed: Not on a GraphQL field definition" ) ;
43+ return ;
44+ }
45+ const declaredType = fieldMatch [ 2 ] ;
46+ services . logger . info ( `Processing field with type: ${ declaredType } ` ) ;
3447
35- // Determine base type and whether it's a list type
36- const isList = declaredType . startsWith ( '[' ) ;
37- const baseType = declaredType . replace ( / [ [ \] ! ] / g, '' ) ; // Remove [] and ! characters
48+ // Determine base type and whether it's a list type
49+ const isList = declaredType . startsWith ( '[' ) ;
50+ const baseType = declaredType . replace ( / [ [ \] ! ] / g, '' ) ; // Remove [] and ! characters
3851
39- // Find matching root operations (queries) that return the same type
40- const ops = Object . entries ( getRootOperationsMap ( ) ) . filter ( ( [ _opName , info ] ) => {
41- return info . returnType === baseType && info . isList === isList ;
42- } ) ;
52+ // Find matching root operations (queries) that return the same type
53+ const ops = Object . entries ( getRootOperationsMap ( ) ) . filter ( ( [ _opName , info ] ) => {
54+ return info . returnType === baseType && info . isList === isList ;
55+ } ) ;
4356
44- if ( ops . length === 0 ) {
45- vscode . window . showInformationMessage (
46- `No matching StepZen queries found for type ${ declaredType } `
47- ) ;
48- return ;
49- }
57+ if ( ops . length === 0 ) {
58+ vscode . window . showInformationMessage (
59+ `No matching StepZen queries found for type ${ declaredType } `
60+ ) ;
61+ services . logger . warn ( `No matching StepZen queries found for type ${ declaredType } ` ) ;
62+ return ;
63+ }
5064
51- // Choose operation if multiple
52- const pickItems = ops . map ( ( [ name ] ) => name ) ;
53- const chosen = pickItems . length === 1
54- ? pickItems [ 0 ]
55- : await vscode . window . showQuickPick ( pickItems , {
56- placeHolder : 'Select a StepZen query to materialize' ,
57- } ) ;
58- if ( ! chosen ) {
59- return ;
60- }
65+ services . logger . info ( `Found ${ ops . length } matching operations for type ${ declaredType } ` ) ;
6166
62- // Get argument names
63- const argNames = getRootOperationsMap ( ) [ chosen ] . args ;
67+ // Choose operation if multiple
68+ const pickItems = ops . map ( ( [ name ] ) => name ) ;
69+ const chosen = pickItems . length === 1
70+ ? pickItems [ 0 ]
71+ : await vscode . window . showQuickPick ( pickItems , {
72+ placeHolder : 'Select a StepZen query to materialize' ,
73+ } ) ;
74+ if ( ! chosen ) {
75+ services . logger . info ( "Add Materializer cancelled by user" ) ;
76+ return ;
77+ }
6478
65- // Build directive snippet with proper indentation
66- const indentUnit = editor . options . insertSpaces
67- ? ' ' . repeat ( editor . options . tabSize as number )
68- : '\t' ;
69- const directiveIndent = baseIndent + indentUnit ;
70- const innerIndent = directiveIndent + indentUnit ;
79+ services . logger . info ( `Selected operation: ${ chosen } ` ) ;
7180
72- const snippetLines : string [ ] = [ ] ;
73- snippetLines . push ( `${ directiveIndent } @materializer(` ) ;
74- snippetLines . push ( `${ innerIndent } query: "${ chosen } "` ) ;
75- snippetLines . push ( `${ innerIndent } arguments: [` ) ;
81+ // Get argument names
82+ const argNames = getRootOperationsMap ( ) [ chosen ] . args ;
7683
77- for ( const arg of argNames ) {
78- snippetLines . push (
79- `${ innerIndent } ${ indentUnit } { name: "${ arg } ", field: "" }`
80- ) ;
81- }
84+ // Build directive snippet with proper indentation
85+ const indentUnit = editor . options . insertSpaces
86+ ? ' ' . repeat ( editor . options . tabSize as number )
87+ : '\t' ;
88+ const directiveIndent = baseIndent + indentUnit ;
89+ const innerIndent = directiveIndent + indentUnit ;
90+
91+ const snippetLines : string [ ] = [ ] ;
92+ snippetLines . push ( `${ directiveIndent } @materializer(` ) ;
93+ snippetLines . push ( `${ innerIndent } query: "${ chosen } "` ) ;
94+ snippetLines . push ( `${ innerIndent } arguments: [` ) ;
95+
96+ for ( const arg of argNames ) {
97+ snippetLines . push (
98+ `${ innerIndent } ${ indentUnit } { name: "${ arg } ", field: "" }`
99+ ) ;
100+ }
82101
83- snippetLines . push ( `${ innerIndent } ]` ) ;
84- snippetLines . push ( `${ directiveIndent } )` ) ;
102+ snippetLines . push ( `${ innerIndent } ]` ) ;
103+ snippetLines . push ( `${ directiveIndent } )` ) ;
85104
86- // Insert snippet below current line
87- const insertPosition = new vscode . Position ( position . line + 1 , 0 ) ;
88- editor . insertSnippet (
89- new vscode . SnippetString ( snippetLines . join ( '\n' ) ) ,
90- insertPosition
91- ) ;
105+ // Insert snippet below current line
106+ const insertPosition = new vscode . Position ( position . line + 1 , 0 ) ;
107+ await editor . insertSnippet (
108+ new vscode . SnippetString ( snippetLines . join ( '\n' ) ) ,
109+ insertPosition
110+ ) ;
111+
112+ services . logger . info ( "Add Materializer completed successfully" ) ;
113+ } catch ( err ) {
114+ handleError ( err ) ;
115+ }
92116}
0 commit comments