1
1
import * as vscode from 'vscode' ;
2
2
import { DevProxyInstall } from './types' ;
3
+ import parse from 'json-to-ast' ;
4
+ import { getASTNode , getRangeFromASTNode } from './helpers' ;
3
5
4
6
export const registerCodeActions = ( context : vscode . ExtensionContext ) => {
5
7
const devProxyInstall =
@@ -15,6 +17,7 @@ export const registerCodeActions = (context: vscode.ExtensionContext) => {
15
17
16
18
registerInvalidSchemaFixes ( devProxyVersion , context ) ;
17
19
registerDeprecatedPluginPathFixes ( context ) ;
20
+ registerLanguageModelFixes ( context ) ;
18
21
} ;
19
22
20
23
function registerInvalidSchemaFixes (
@@ -130,3 +133,126 @@ function registerDeprecatedPluginPathFixes(context: vscode.ExtensionContext) {
130
133
) ,
131
134
) ;
132
135
}
136
+
137
+ function registerLanguageModelFixes ( context : vscode . ExtensionContext ) {
138
+ const languageModelMissing : vscode . CodeActionProvider = {
139
+ provideCodeActions : ( document , range , context , token ) => {
140
+ // Check if the current range intersects with a missing language model diagnostic
141
+ const currentDiagnostic = context . diagnostics . find ( diagnostic => {
142
+ return (
143
+ diagnostic . code === 'missingLanguageModel' &&
144
+ diagnostic . range . intersection ( range )
145
+ ) ;
146
+ } ) ;
147
+
148
+ // Only provide language model actions if user is on a missing language model diagnostic
149
+ if ( ! currentDiagnostic ) {
150
+ return [ ] ;
151
+ }
152
+
153
+ const fixes : vscode . CodeAction [ ] = [ ] ;
154
+
155
+ // Fix to add languageModel configuration
156
+ const addLanguageModelFix = new vscode . CodeAction (
157
+ 'Add languageModel configuration' ,
158
+ vscode . CodeActionKind . QuickFix ,
159
+ ) ;
160
+
161
+ addLanguageModelFix . edit = new vscode . WorkspaceEdit ( ) ;
162
+
163
+ try {
164
+ // Parse the document using json-to-ast for accurate insertion
165
+ const documentNode = parse ( document . getText ( ) ) as parse . ObjectNode ;
166
+
167
+ // Check if languageModel already exists
168
+ const existingLanguageModel = getASTNode (
169
+ documentNode . children ,
170
+ 'Identifier' ,
171
+ 'languageModel'
172
+ ) ;
173
+
174
+ if ( existingLanguageModel ) {
175
+ // languageModel exists but enabled might be false or missing
176
+ const languageModelObjectNode = existingLanguageModel . value as parse . ObjectNode ;
177
+ const enabledNode = getASTNode (
178
+ languageModelObjectNode . children ,
179
+ 'Identifier' ,
180
+ 'enabled'
181
+ ) ;
182
+
183
+ if ( enabledNode ) {
184
+ // Replace the enabled value
185
+ addLanguageModelFix . edit . replace (
186
+ document . uri ,
187
+ getRangeFromASTNode ( enabledNode . value ) ,
188
+ 'true'
189
+ ) ;
190
+ } else {
191
+ // Add enabled property
192
+ const insertPosition = new vscode . Position (
193
+ languageModelObjectNode . loc ! . end . line - 1 ,
194
+ languageModelObjectNode . loc ! . end . column - 1
195
+ ) ;
196
+ addLanguageModelFix . edit . insert (
197
+ document . uri ,
198
+ insertPosition ,
199
+ '\n "enabled": true'
200
+ ) ;
201
+ }
202
+ } else {
203
+ // Add new languageModel object
204
+ // Find the last property to insert after it
205
+ const lastProperty = documentNode . children [ documentNode . children . length - 1 ] as parse . PropertyNode ;
206
+ const insertPosition = new vscode . Position (
207
+ lastProperty . loc ! . end . line - 1 ,
208
+ lastProperty . loc ! . end . column
209
+ ) ;
210
+
211
+ addLanguageModelFix . edit . insert (
212
+ document . uri ,
213
+ insertPosition ,
214
+ ',\n "languageModel": {\n "enabled": true\n }'
215
+ ) ;
216
+ }
217
+ } catch ( error ) {
218
+ // Fallback to simple text-based insertion
219
+ const documentText = document . getText ( ) ;
220
+ const lines = documentText . split ( '\n' ) ;
221
+
222
+ // Find where to insert the languageModel config
223
+ let insertLine = lines . length - 1 ;
224
+ for ( let i = lines . length - 1 ; i >= 0 ; i -- ) {
225
+ if ( lines [ i ] . includes ( '}' ) ) {
226
+ insertLine = i ;
227
+ break ;
228
+ }
229
+ }
230
+
231
+ const hasContentBefore = lines . slice ( 0 , insertLine ) . some ( line =>
232
+ line . trim ( ) && ! line . trim ( ) . startsWith ( '{' ) && ! line . trim ( ) . startsWith ( '/*' ) && ! line . trim ( ) . startsWith ( '*' )
233
+ ) ;
234
+
235
+ const languageModelConfig = hasContentBefore ?
236
+ ',\n "languageModel": {\n "enabled": true\n }' :
237
+ ' "languageModel": {\n "enabled": true\n }' ;
238
+
239
+ const insertPosition = new vscode . Position ( insertLine , 0 ) ;
240
+ addLanguageModelFix . edit . insert ( document . uri , insertPosition , languageModelConfig + '\n' ) ;
241
+ }
242
+
243
+ addLanguageModelFix . isPreferred = true ;
244
+ fixes . push ( addLanguageModelFix ) ;
245
+
246
+ return fixes ;
247
+ } ,
248
+ } ;
249
+
250
+ // Code action for missing language model configuration
251
+ context . subscriptions . push (
252
+ vscode . languages . registerCodeActionsProvider ( 'json' , languageModelMissing ) ,
253
+ ) ;
254
+
255
+ context . subscriptions . push (
256
+ vscode . languages . registerCodeActionsProvider ( 'jsonc' , languageModelMissing ) ,
257
+ ) ;
258
+ }
0 commit comments