8000 Adding support for Typeinference based on runtime variable values by powercode · Pull Request #2744 · PowerShell/PowerShell · GitHub
[go: up one dir, main page]

Skip to content

Adding support for Typeinference based on runtime variable values #2744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 7, 2017
Merged
Show file tree
Hide file tree
Changes from 18 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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ gen

# TestsResults
TestsResults*.xml

# Resharper settings
PowerShell.sln.DotSettings.user

Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ private static List<CompletionResult> InvokeLegacyTabExpansion(PowerShell powers
char quote;
var lastword = LastWordFinder.FindLastWord(legacyInput, out replacementIndex, out quote);
replacementLength = legacyInput.Length - replacementIndex;
var helper = new CompletionExecutionHelper(powershell);
var helper = new PowerShellExecutionHelper(powershell);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This replacement is reasonable from the commits history point of view, but in the final diff, I don't see why do we want to remove one class/file and replace it with another one with the similar duties. Maybe we should keep the same name, so the caller doesn't need to change?

It will also help, if PowerShell team will decide to bring some changes back to windows, for that see https://github.com/PowerShell/PowerShell/blob/master/docs/dev-process/map-json-files.md


powershell.AddCommand("TabExpansion").AddArgument(legacyInput).AddArgument(lastword);

Expand Down Expand Up @@ -749,7 +749,7 @@ internal CommandAndName(PSObject command, PSSnapinQualifiedName commandName)
/// <param name="quote"></param>
/// <param name="completingAtStartOfLine"></param>
/// <returns></returns>
internal static List<CompletionResult> PSv2GenerateMatchSetOfCmdlets(CompletionExecutionHelper helper, string lastWord, string quote, bool completingAtStartOfLine)
internal static List<CompletionResult> PSv2GenerateMatchSetOfCmdlets(PowerShellExecutionHelper helper, string lastWord, string quote, bool completingAtStartOfLine)
{
var results = new List<CompletionResult>();
bool isSnapinSpecified;
Expand Down Expand Up @@ -864,7 +864,7 @@ private static void PrependSnapInNameForSameCmdletNames(CommandAndName[] cmdlets

#region "Handle File Names"

internal static List<CompletionResult> PSv2GenerateMatchSetOfFiles(CompletionExecutionHelper helper, string lastWord, bool completingAtStartOfLine, string quote)
internal static List<CompletionResult> PSv2GenerateMatchSetOfFiles(PowerShellExecutionHelper helper, string lastWord, bool completingAtStartOfLine, string quote)
{
var results = new List<CompletionResult>();

Expand Down Expand Up @@ -926,7 +926,7 @@ internal static List<CompletionResult> PSv2GenerateMatchSetOfFiles(CompletionExe

bool? isContainer = SafeGetProperty<bool?>(combinedMatch.Item, "PSIsContainer");
string childName = SafeGetProperty<string>(combinedMatch.Item, "PSChildName");
string toolTip = CompletionExecutionHelper.SafeToString(combinedMatch.ConvertedPath);
string toolTip = PowerShellExecutionHelper.SafeToString(combinedMatch.ConvertedPath);

if (isContainer != null && childName != null && toolTip != null)
{
Expand Down Expand Up @@ -1034,7 +1034,7 @@ private static T SafeGetProperty<T>(PSObject psObject, string propertyName)
return default(T);
}

private static bool PSv2ShouldFullyQualifyPathsPath(CompletionExecutionHelper helper, string lastWord)
private static bool PSv2ShouldFullyQualifyPathsPath(PowerShellExecutionHelper helper, string lastWord)
{
// These are special cases, as they represent cases where the user expects to
// see the full path.
Expand Down Expand Up @@ -1068,7 +1068,7 @@ internal PathItemAndConvertedPath(string path, PSObject item, string convertedPa
}
}

private static List<PathItemAndConvertedPath> PSv2FindMatches(CompletionExecutionHelper helper, string path, bool shouldFullyQualifyPaths)
private static List<PathItemAndConvertedPath> PSv2FindMatches(PowerShellExecutionHelper helper, string path, bool shouldFullyQualifyPaths)
{
Diagnostics.Assert(!String.IsNullOrEmpty(path), "path should have a value");
var result = new List<PathItemAndConvertedPath>();
Expand Down Expand Up @@ -1113,9 +1113,9 @@ private static List<PathItemAndConvertedPath> PSv2FindMatches(CompletionExecutio
}

result.Add(new PathItemAndConvertedPath(
CompletionExecutionHelper.SafeToString(objectPath),
PowerShellExecutionHelper.SafeToString(objectPath),
item,
CompletionExecutionHelper.SafeToString(convertedPath)));
PowerShellExecutionHelper.SafeToString(convertedPath)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal class CompletionContext
internal Token TokenBeforeCursor { get; set; }
internal IScriptPosition CursorPosition { get; set; }

internal CompletionExecutionHelper Helper { get; set; }
internal PowerShellExecutionHelper Helper { get; set; }
internal Hashtable Options { get; set; }
internal Dictionary<string, ScriptBlock> CustomArgumentCompleters { get; set; }
internal Dictionary<string, ScriptBlock> NativeArgumentCompleters { get; set; }
Expand All @@ -33,7 +33,7 @@ internal class CompletionContext
internal int ReplacementLength { get; set; }
internal ExecutionContext ExecutionContext { get; set; }
internal PseudoBindingInfo PseudoBindingInfo { get; set; }
internal TypeDefinitionAst CurrentTypeDefinitionAst { get; set; }
internal TypeInferenceContext TypeInferenceContext { get; set; }

internal bool GetOption(string option, bool @default)
{
Expand Down Expand Up @@ -96,15 +96,26 @@ private static bool IsCursorOutsideOfExtent(IScriptPosition cursor, IScriptExten
return cursor.Offset < extent.StartOffset || cursor.Offset > extent.EndOffset;
}

internal CompletionContext CreateCompletionContext(ExecutionContext executionContext)

internal CompletionContext CreateCompletionContext(PowerShell powerShell)
{
var typeInferenceContext = new TypeInferenceContext(powerShell);
return InitializeCompletionContext(typeInferenceContext);
}
internal CompletionContext CreateCompletionContext(TypeInferenceContext typeInferenceContext)
{
return InitializeCompletionContext(typeInferenceContext);
}

private CompletionContext InitializeCompletionContext(TypeInferenceContext typeInferenceContext)
{
Token tokenBeforeCursor = null;
IScriptPosition positionForAstSearch = _cursorPosition;
var adjustLineAndColumn = false;
var tokenAtCursor = _tokens.LastOrDefault(token => IsCursorWithinOrJustAfterExtent(_cursorPosition, token.Extent) && IsInterestingToken(token));
var tokenAtCursor = InterstingTokenAtCursorOrDefault(_tokens, _cursorPosition);
if (tokenAtCursor == null)
{
tokenBeforeCursor = _tokens.LastOrDefault(token => IsCursorAfterExtent(_cursorPosition, token.Extent) && IsInterestingToken(token));
tokenBeforeCursor = InterstingTokenBeforeCursorOrDefault(_tokens, _cursorPosition);
if (tokenBeforeCursor != null)
{
positionForAstSearch = tokenBeforeCursor.Extent.EndScriptPosition;
Expand All @@ -114,17 +125,22 @@ internal CompletionContext CreateCompletionContext(ExecutionContext executionCon
else
{
var stringExpandableToken = tokenAtCursor as StringExpandableToken;
if (stringExpandableToken != null && stringExpandableToken.NestedTokens != null)
if (stringExpandableToken?.NestedTokens != null)
{
tokenAtCursor =
stringExpandableToken.NestedTokens.LastOrDefault(
token => IsCursorWithinOrJustAfterExtent(_cursorPosition, token.Extent) && IsInterestingToken(token)) ?? stringExpandableToken;
tokenAtCursor = InterstingTokenAtCursorOrDefault(stringExpandableToken.NestedTokens, _cursorPosition) ?? stringExpandableToken;
}
}

var asts = AstSearcher.FindAll(_ast, ast => IsCursorWithinOrJustAfterExtent(positionForAstSearch, ast.Extent), searchNestedScriptBlocks: true).ToList();

Diagnostics.Assert(tokenAtCursor == null || tokenBeforeCursor == null, "Only one of these tokens can be non-null");

if (typeInferenceContext.CurrentTypeDefinitionAst == null)
{
typeInferenceContext.CurrentTypeDefinitionAst = Ast.GetAncestorTypeDefinitionAst(asts.Last());
}
ExecutionContext executionContext = typeInferenceContext.ExecutionContext;

return new CompletionContext
{
TokenAtCursor = tokenAtCursor,
Expand All @@ -134,12 +150,24 @@ internal CompletionContext CreateCompletionContext(ExecutionContext executionCon
Options = _options,
ExecutionContext = executionContext,
ReplacementIndex = adjustLineAndColumn ? _cursorPosition.Offset : 0,
CurrentTypeDefinitionAst = Ast.GetAncestorTypeDefinitionAst(asts.Last()),
TypeInferenceContext = typeInferenceContext,
Helper = typeInferenceContext.Helper,
CustomArgumentCompleters = executionContext.CustomArgumentCompleters,
NativeArgumentCompleters = executionContext.NativeArgumentCompleters,
};
}

private static Token InterstingTokenAtCursorOrDefault(IEnumerable<Token> tokens, IScriptPosition cursorPosition)
{
return tokens.LastOrDefault(token => IsCursorWithinOrJustAfterExtent(cursorPosition, token.Extent) && IsInterestingToken(token));
}

private static Token InterstingTokenBeforeCursorOrDefault(IEnumerable<Token> tokens, IScriptPosition cursorPosition)
{
return tokens.LastOrDefault(token => IsCursorAfterExtent(cursorPosition, token.Extent) && IsInterestingToken(token));
}


private static Ast GetLastAstAtCursor(ScriptBlockAst scriptBlockAst, IScriptPosition cursorPosition)
{
var asts = AstSearcher.FindAll(scriptBlockAst, ast => IsCursorRightAfterExtent(cursorPosition, ast.Extent), searchNestedScriptBlocks: true);
Expand Down Expand Up @@ -278,8 +306,7 @@ private static bool IsTokenTheSame(Token x, Token y)

internal List<CompletionResult> GetResults(PowerShell powerShell, out int replacementIndex, out int replacementLength)
{
var completionContext = CreateCompletionContext(powerShell.GetContextFromTLS());
completionContext.Helper = new CompletionExecutionHelper(powerShell);
var completionContext = CreateCompletionContext(powerShell);

PSLanguageMode? previousLanguageMode = null;
try
Expand Down Expand Up @@ -1167,8 +1194,7 @@ private List<CompletionResult> GetResultForString(CompletionContext completionCo
cursorIndexInString = strValue.Length;

var analysis = new CompletionAnalysis(_ast, _tokens, _cursorPosition, _options);
var subContext = analysis.CreateCompletionContext(completionContext.ExecutionContext);
subContext.Helper = completionContext.Helper;
var subContext = analysis.CreateCompletionContext(completionContext.TypeInferenceContext);

int subReplaceIndex, subReplaceLength;
var subResult = analysis.GetResultHelper(subContext, out subReplaceIndex, out subReplaceLength, true);
Expand Down
Loading
0