Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,12 @@ internal List<CompletionResult> GetResultHelper(CompletionContext completionCont
if (result == null || result.Count == 0)
{
result = GetResultForHashtable(completionContext);
// Handles the following scenario: [ipaddress]@{Address=""; <Tab> }
if (result?.Count > 0)
{
replacementIndex = completionContext.CursorPosition.Offset;
replacementLength = 0;
}
}

if (result == null || result.Count == 0)
Expand All @@ -950,59 +956,56 @@ internal List<CompletionResult> GetResultHelper(CompletionContext completionCont
// Helper method to auto complete hashtable key
private static List<CompletionResult> GetResultForHashtable(CompletionContext completionContext)
{
var lastAst = completionContext.RelatedAsts.Last();
HashtableAst tempHashtableAst = null;
IScriptPosition cursor = completionContext.CursorPosition;
var hashTableAst = lastAst as HashtableAst;
if (hashTableAst != null)
Ast lastRelatedAst = null;
var cursorPosition = completionContext.CursorPosition;

// Enumeration is used over the LastAst pattern because empty lines following a key-value pair will set LastAst to the value.
// Example:
// @{
// Key1="Value1"
// <Tab>
// }
// In this case the last 3 Asts will be StringConstantExpression, CommandExpression, and Pipeline instead of the expected Hashtable
for (int i = completionContext.RelatedAsts.Count - 1; i >= 0; i--)
{
Ast ast = completionContext.RelatedAsts[i];
if (cursorPosition.Offset >= ast.Extent.StartOffset && cursorPosition.Offset <= ast.Extent.EndOffset)
{
lastRelatedAst = ast;
break;
}
}

if (lastRelatedAst is HashtableAst hashtableAst)
{
// Check if the cursor within the hashtable
if (cursor.Offset < hashTableAst.Extent.EndOffset)
// Cursor is just after the hashtable: @{}<Tab>
if (completionContext.TokenAtCursor is not null && completionContext.TokenAtCursor.Kind == TokenKind.RCurly)
{
tempHashtableAst = hashTableAst;
return null;
}
else if (cursor.Offset == hashTableAst.Extent.EndOffset)

bool cursorIsWithinOrOnSameLineAsKeypair = false;
foreach (var pair in hashtableAst.KeyValuePairs)
{
// Exclude the scenario that cursor at the end of hashtable, i.e. after '}'
if (completionContext.TokenAtCursor == null ||
completionContext.TokenAtCursor.Kind != TokenKind.RCurly)
if (cursorPosition.Offset >= pair.Item1.Extent.StartOffset
&& (cursorPosition.Offset <= pair.Item2.Extent.EndOffset || cursorPosition.LineNumber == pair.Item2.Extent.EndLineNumber))
{
tempHashtableAst = hashTableAst;
cursorIsWithinOrOnSameLineAsKeypair = true;
break;
}
}
}
else
{
// Handle property completion on a blank line for DynamicKeyword statement
Ast lastChildofHashtableAst;
hashTableAst = Ast.GetAncestorHashtableAst(lastAst, out lastChildofHashtableAst);

// Check if the hashtable within a DynamicKeyword statement
if (hashTableAst != null)
if (cursorIsWithinOrOnSameLineAsKeypair)
{
var keywordAst = Ast.GetAncestorAst<DynamicKeywordStatementAst>(hashTableAst);
if (keywordAst != null)
var tokenBeforeOrAtCursor = completionContext.TokenBeforeCursor ?? completionContext.TokenAtCursor;
if (tokenBeforeOrAtCursor.Kind != TokenKind.Semi)
{
// Handle only empty line
if (string.IsNullOrWhiteSpace(cursor.Line))
{
// Check if the cursor outside of last child of hashtable and within the hashtable
if (cursor.Offset > lastChildofHashtableAst.Extent.EndOffset &&
cursor.Offset <= hashTableAst.Extent.EndOffset)
{
tempHashtableAst = hashTableAst;
}
}
return null;
}
}
}

hashTableAst = tempHashtableAst;
if (hashTableAst != null)
{
completionContext.ReplacementIndex = completionContext.CursorPosition.Offset;
completionContext.ReplacementLength = 0;
return CompletionCompleters.CompleteHashtableKey(completionContext, hashTableAst);
return CompletionCompleters.CompleteHashtableKey(completionContext, hashtableAst);
}

return null;
Expand Down
Loading