@@ -71,14 +71,13 @@ ILanguageServerConfiguration config
71
71
72
72
ScriptPositionAdapter position = request . Position ;
73
73
Ast ? target = FindRenamableSymbol ( scriptFile , position ) ;
74
- if ( target is null ) { return null ; }
75
74
76
- // Will implicitly convert to RangeOrPlaceholder and adjust to 0-based
77
- return target switch
78
- {
79
- FunctionDefinitionAst funcAst => GetFunctionNameExtent ( funcAst ) ,
80
- _ => new ScriptExtentAdapter ( target . Extent )
81
- } ;
75
+ // Since 3.16 we can simply basically return a DefaultBehavior true or null to signal to the client that the position is valid for rename and it should use its default selection criteria (which is probably the language semantic highlighting or grammar). For the current scope of the rename provider, this should be fine, but we have the option to supply the specific range in the future for special cases.
76
+ RangeOrPlaceholderRange ? renamable = target is null ? null : new RangeOrPlaceholderRange
77
+ (
78
+ new RenameDefaultBehavior ( ) { DefaultBehavior = true }
79
+ ) ;
80
+ return renamable ;
82
81
}
83
82
84
83
public async Task < WorkspaceEdit ? > RenameSymbol ( RenameParams request , CancellationToken cancellationToken )
@@ -176,25 +175,36 @@ internal static TextEdit[] RenameVariable(Ast symbol, Ast scriptAst, RenameParam
176
175
{
177
176
if ( stringAst . Parent is not CommandAst parent ) { return null ; }
178
177
if ( parent . GetCommandName ( ) != stringAst . Value ) { return null ; }
178
+ if ( parent . CommandElements [ 0 ] != stringAst ) { return null ; }
179
+ // TODO: Potentially find if function was defined earlier in the file to avoid native executable renames and whatnot?
180
+ }
181
+
182
+ // Only the function name is valid for rename, not other components
183
+ if ( ast is FunctionDefinitionAst funcDefAst )
184
+ {
185
+ if ( ! GetFunctionNameExtent ( funcDefAst ) . Contains ( position ) )
186
+ {
187
+ return null ;
188
+ }
179
189
}
180
190
181
191
return ast ;
182
192
}
183
193
184
194
195
+ /// <summary>
196
+ /// Return an extent that only contains the position of the name of the function, for Client highlighting purposes.
197
+ /// </summary>
185
198
private static ScriptExtentAdapter GetFunctionNameExtent ( FunctionDefinitionAst ast )
186
199
{
187
200
string name = ast . Name ;
188
201
// FIXME: Gather dynamically from the AST and include backticks and whatnot that might be present
189
202
int funcLength = "function " . Length ;
190
203
ScriptExtentAdapter funcExtent = new ( ast . Extent ) ;
204
+ funcExtent . Start = funcExtent . Start . Delta ( 0 , funcLength ) ;
205
+ funcExtent . End = funcExtent . Start . Delta ( 0 , name . Length ) ;
191
206
192
- // Get a range that represents only the function name
193
- return funcExtent with
194
- {
195
- Start = funcExtent . Start . Delta ( 0 , funcLength ) ,
196
- End = funcExtent . Start . Delta ( 0 , funcLength + name . Length )
197
- } ;
207
+ return funcExtent ;
198
208
}
199
209
}
200
210
@@ -219,41 +229,47 @@ public static class AstExtensions
219
229
220
230
// This will be updated with each loop, and re-Find to dig deeper
221
231
Ast ? mostSpecificAst = null ;
232
+ Ast ? currentAst = ast ;
222
233
223
234
do
224
235
{
225
- ast = ast . Find ( currentAst =>
236
+ currentAst = currentAst . Find ( thisAst =>
226
237
{
227
- if ( currentAst == mostSpecificAst ) { return false ; }
238
+ if ( thisAst == mostSpecificAst ) { return false ; }
228
239
229
240
int line = position . LineNumber ;
230
241
int column = position . ColumnNumber ;
231
242
232
243
// Performance optimization, skip statements that don't contain the position
233
244
if (
234
- currentAst . Extent . EndLineNumber < line
235
- || currentAst . Extent . StartLineNumber > line
236
- || ( currentAst . Extent . EndLineNumber == line && currentAst . Extent . EndColumnNumber < column )
237
- || ( currentAst . Extent . StartLineNumber == line && currentAst . Extent . StartColumnNumber > column )
245
+ thisAst . Extent . EndLineNumber < line
246
+ || thisAst . Extent . StartLineNumber > line
247
+ || ( thisAst . Extent . EndLineNumber == line && thisAst . Extent . EndColumnNumber < column )
248
+ || ( thisAst . Extent . StartLineNumber == line && thisAst . Extent . StartColumnNumber > column )
238
249
)
239
250
{
240
251
return false ;
241
252
}
242
253
243
- if ( allowedTypes is not null && ! allowedTypes . Contains ( currentAst . GetType ( ) ) )
254
+ if ( allowedTypes is not null && ! allowedTypes . Contains ( thisAst . GetType ( ) ) )
244
255
{
245
256
return false ;
246
257
}
247
258
248
- if ( new ScriptExtentAdapter ( currentAst . Extent ) . Contains ( position ) )
259
+ if ( new ScriptExtentAdapter ( thisAst . Extent ) . Contains ( position ) )
249
260
{
250
- mostSpecificAst = currentAst ;
251
- return true ; //Stops the find
261
+ mostSpecificAst = thisAst ;
262
+ return true ; //Stops this particular find and looks more specifically
252
263
}
253
264
254
265
return false ;
255
266
} , true ) ;
256
- } while ( ast is not null ) ;
267
+
268
+ if ( currentAst is not null )
269
+ {
270
+ mostSpecificAst = currentAst ;
271
+ }
272
+ } while ( currentAst is not null ) ;
257
273
258
274
return mostSpecificAst ;
259
275
}
@@ -490,7 +506,10 @@ internal record ScriptExtentAdapter(IScriptExtent extent) : IScriptExtent
490
506
491
507
public static implicit operator ScriptExtent ( ScriptExtentAdapter adapter ) => adapter ;
492
508
493
- public static implicit operator RangeOrPlaceholderRange ( ScriptExtentAdapter adapter ) => new ( ( Range ) adapter ) ;
509
+ public static implicit operator RangeOrPlaceholderRange ( ScriptExtentAdapter adapter ) => new ( ( Range ) adapter )
510
+ {
511
+ DefaultBehavior = new ( ) { DefaultBehavior = false }
512
+ } ;
494
513
495
514
public IScriptPosition StartScriptPosition => Start ;
496
515
public IScriptPosition EndScriptPosition => End ;
0 commit comments