Skip to content

Fix tab completions for a hash table - #6839

Merged
Ilya (iSazonov) merged 3 commits into
PowerShell:masterfrom
iSazonov:fix-tabcompletion
May 21, 2018
Merged

Fix tab completions for a hash table#6839
Ilya (iSazonov) merged 3 commits into
PowerShell:masterfrom
iSazonov:fix-tabcompletion

Conversation

@iSazonov

Copy link
Copy Markdown
Collaborator

PR Summary

Fix #5322.

Now working:

  • Get-Date | Sort-Object @{Expression=<tab>
  • Get-Date | Sort-Object @{Expression=...;<tab>

PR Checklist

replacementLength = 0;
break;

case TokenKind.Semi:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does adding this case affect get-something; e<TAB> - in other words, no hashtable, just simple command completion?

@iSazonov Ilya (iSazonov) May 8, 2018

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't see the side affect.
Maybe add the test?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-check get-something; e<Tab> - in Windows PowerShell 5.1 and in PowerShell Core 6.0 simple command completion works - nothing new added in the PR.

@iSazonov

Copy link
Copy Markdown
Collaborator Author

Steve Lee (@SteveL-MSFT) Dongbo Wang (@daxian-dbw) Could you please review too?


case TokenKind.Semi:
// Handle scenarios such as 'gci | Format-Table @{Label=...;<tab>'
result = GetResultForHashtable(completionContext);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get-something;<tab> does go through this path. It's better to check if (lastAst is HashtableAst) before calling GetResultForHashtable.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}
// Handle scenarios such as 'gci | Format-Table @{Label=<tab>'
return null;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the call to GetResultForEnumPropertyValueOfDSCResource.
How about changing to this:

case TokenKind.LParen:
    {
        if (lastAst is AttributeAst)
        {
            ...
        }
        else if (lastAst.Parent is DynamicKeywordStatementAst)  // <-- change here
        {
            ...
        }
        else if (lastAst is HashtableAst hashTableAst && CheckForPendingAssignment(hashTableAst)) // <-- change here
        {
            return result;
        }
        break;
    }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second condition doesn't work for configuration foo { File ab { Attributes =( test - really lastAst.Parent is CommandExpressionAst.

Fixed.

$result.CompletionMatches.Count | Should -Be 3
$result.CompletionMatches[0].CompletionText | Should -Be 'Expression'
$result.CompletionMatches[1].CompletionText | Should -Be 'Ascending'
$result.CompletionMatches[2].CompletionText | Should -Be 'Descending'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test succeeds even without changes in this PR. You need to check ReplacementIndex and ReplacementLength, as they were -1 previously and changes in this PR should fix them.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

{
//
// Handle auto completion for enum/dependson property of DSC resource,
// 1. Handle scenarios such as 'configuration foo { File ab { Attributes ='

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle auto completion for enum/dependson property of DSC resource

The example configuration foo { File ab { Attributes = is a completion for enum property, so it should not be marked as 1..

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

result = GetResultForAttributeArgument(completionContext, ref replacementIndex, ref replacementLength);
}
else
else if (lastAst.Parent is DynamicKeywordStatementAst || lastAst.Parent is CommandExpressionAst)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are making two special checks here. Maybe we should only have one special check, like the following. What do you think?

if (lastAst is AttributeAst)
{
    // the original attribute handling
}
else if (lastAst is HashtableAst hashTableAst &&
         !(lastAst.Parent is DynamicKeywordStatementAst) &&
         CheckForPendingAssignment(hashTableAst))
{
    return null;
}
else
{
    // the original else block
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks!

Fixed.

$cmd = "Get-Date | Sort-Object @{Expression=...;"
$result = TabExpansion2 -inputScript $cmd -cursorColumn $cmd.Length
$result.CurrentMatchIndex | Should -Be -1
$result.ReplacementIndex | Should -Be 40

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And ReplacementLength?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

$result.CompletionMatches[2].CompletionText | Should -Be 'Descending'
$result.CompletionMatches[0].CompletionText | Should -Be 'Expression'
$result.CompletionMatches[1].CompletionText | Should -Be 'Ascending'
$result.CompletionMatches[2].CompletionText | Should -Be 'Descending'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$result.CompletionMatches[2].CompletionText is checked twice.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was for ReplacementLength :-)

Fixed.

@iSazonov

Copy link
Copy Markdown
Collaborator Author

The while code is very tricky and sensetive 😕 and crush PowerShell if something wrong. Maybe we should make it more robust.

@daxian-dbw Dongbo Wang (daxian-dbw) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Ilya (@iSazonov) What while code were you referring to?

@iSazonov

Copy link
Copy Markdown
Collaborator Author

I means our Completion code - if I return wrong index PowerShell is crashed. Asts can be combined in many ways. Can we be sure that we tested all their? The code is complex and tricky - can we create simple algorithm? Using visitors?

@iSazonov

Copy link
Copy Markdown
Collaborator Author

Jason Shirk (@lzybkr) Steve Lee (@SteveL-MSFT) Do you have any comments?

@iSazonov
Ilya (iSazonov) merged commit 626a83b into PowerShell:master May 21, 2018
@iSazonov
Ilya (iSazonov) deleted the fix-tabcompletion branch May 21, 2018 04:06
@daxian-dbw

Copy link
Copy Markdown
Member

Ilya (@iSazonov) Sorry for the late reply. I agree the tab completion code is a bit hard to organize now. Many changes have been made that are very specific to the scenarios they try to solve, so you can see checks in CompletionAnalysis that are tied to one particular scenario which is hard to understand just by reading the code.

However, the crash is possibly not related to tab completion, but the code rending results to console. If you mess up the index, the rendering code might do weird bad things. I don't think a visitor can help much here, as many checks need to inspect ancestors of an ast.

@iSazonov

Copy link
Copy Markdown
Collaborator Author

Dongbo Wang (@daxian-dbw) Thanks for great comment!

Thatgfsj (Thatgfsj) pushed a commit to Thatgfsj-contribs/PowerShell that referenced this pull request Aug 6, 2026
Now working:
- Get-Date | Sort-Object @{Expression=<tab>
- Get-Date | Sort-Object @{Expression=...;<tab>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Completion of hash table key has invalid replacement index/length

3 participants