Skip to content

Commit 56b41a9

Browse files
JustinGroteCopilot
andauthored
Handle use case where there are multiple spaces after the function keyword
Co-authored-by: Copilot <[email protected]>
1 parent 48f308b commit 56b41a9

1 file changed

Lines changed: 106 additions & 2 deletions

File tree

src/PowerShellEditorServices/Utility/AstExtensions.cs

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,13 +576,117 @@ public static bool HasParent(this Ast ast, Ast parent)
576576
/// </summary>
577577
internal static ScriptExtentAdapter GetFunctionNameExtent(this FunctionDefinitionAst ast)
578578
{
579+
ScriptExtentAdapter funcExtent = new(ast.Extent);
580+
string? extentText = ast.Extent.Text;
581+
582+
if (TryGetFunctionNameOffsets(extentText, out int nameStartOffset, out int nameEndOffset))
583+
{
584+
funcExtent.Start = GetPositionAtOffset(funcExtent.Start, extentText!, nameStartOffset);
585+
funcExtent.End = GetPositionAtOffset(funcExtent.Start, extentText!, nameEndOffset);
586+
return funcExtent;
587+
}
588+
589+
// Fallback for unexpected input: preserve the previous behavior as closely as possible.
579590
string name = ast.Name;
580-
// FIXME: Gather dynamically from the AST and include backticks and whatnot that might be present
581591
int funcLength = "function ".Length;
582-
ScriptExtentAdapter funcExtent = new(ast.Extent);
583592
funcExtent.Start = funcExtent.Start.Delta(0, funcLength);
584593
funcExtent.End = funcExtent.Start.Delta(0, name.Length);
585594

586595
return funcExtent;
587596
}
597+
598+
private static ScriptPosition GetPositionAtOffset(
599+
ScriptPosition basePosition,
600+
string text,
601+
int offset)
602+
{
603+
int lineDelta = 0;
604+
int columnDelta = 0;
605+
606+
for (int i = 0; i < offset; i++)
607+
{
608+
char c = text[i];
609+
if (c == '\r')
610+
{
611+
if (i + 1 < offset && text[i + 1] == '\n')
612+
{
613+
i++;
614+
}
615+
616+
lineDelta++;
617+
columnDelta = 0;
618+
}
619+
else if (c == '\n')
620+
{
621+
lineDelta++;
622+
columnDelta = 0;
623+
}
624+
else
625+
{
626+
columnDelta++;
627+
}
628+
}
629+
630+
return basePosition.Delta(lineDelta, columnDelta);
631+
}
632+
633+
private static bool TryGetFunctionNameOffsets(
634+
string? text,
635+
out int nameStartOffset,
636+
out int nameEndOffset)
637+
{
638+
nameStartOffset = 0;
639+
nameEndOffset = 0;
640+
641+
if (string.IsNullOrEmpty(text))
642+
{
643+
return false;
644+
}
645+
646+
const string functionKeyword = "function";
647+
int functionIndex = text.IndexOf(functionKeyword, StringComparison.OrdinalIgnoreCase);
648+
if (functionIndex < 0)
649+
{
650+
return false;
651+
}
652+
653+
int index = functionIndex + functionKeyword.Length;
654+
while (index < text.Length && char.IsWhiteSpace(text[index]))
655+
{
656+
index++;
657+
}
658+
659+
if (index >= text.Length)
660+
{
661+
return false;
662+
}
663+
664+
nameStartOffset = index;
665+
666+
while (index < text.Length)
667+
{
668+
char current = text[index];
669+
670+
if (current == '`')
671+
{
672+
index++;
673+
if (index < text.Length)
674+
{
675+
index++;
676+
}
677+
678+
continue;
679+
}
680+
681+
if (char.IsWhiteSpace(current) || current == '{' || current == '(')
682+
{
683+
break;
684+
}
685+
686+
index++;
687+
}
688+
689+
nameEndOffset = index;
690+
return nameEndOffset > nameStartOffset;
691+
}
588692
}

0 commit comments

Comments
 (0)