private Stack <string> FindAccessorChain(IConsoleInput consoleInput, int chainEndIndex) { _accessorChain.Clear(); while (true) { int indices = FindBoundaryIndices(consoleInput, chainEndIndex); int startIndex = indices & 0xff; int length = indices >> 16; string chainLink = consoleInput.Substring(startIndex, length).Trim(); _accessorChain.Push(chainLink); int previousLinkEndIndex = FindPreviousLinkEndIndex(consoleInput, startIndex - 1); if (chainEndIndex < 0) { return(_accessorChain); } AutocompletionType chainType = FindAutocompleteType(consoleInput, startIndex); if (chainType == AutocompletionType.Accessor) { chainEndIndex = previousLinkEndIndex; continue; } break; } return(_accessorChain); }
public void Autocomplete(IConsoleInput consoleInput, bool isNextValue) { // Which context we in, method or regular. AutocompletionContextResult contextResult = FindAutocompletionContext(consoleInput); Type typeToPrefer = null; if (contextResult.Context == AutocompletionContext.Method) { long newCommandLength_whichParamAt_newStartIndex_numParams = FindParamIndexNewStartIndexAndNumParams(consoleInput, contextResult.StartIndex); int chainEndIndex = FindPreviousLinkEndIndex(consoleInput, contextResult.StartIndex - 1); if (chainEndIndex >= 0) { Stack <string> accessorChain = FindAccessorChain(consoleInput, chainEndIndex); Member lastChainLink = FindLastChainLinkMember(accessorChain); if (lastChainLink?.ParameterInfo != null) { var numParams = (int)(newCommandLength_whichParamAt_newStartIndex_numParams & 0xff); ParameterInfo[] overload = null; for (int i = numParams; i <= lastChainLink.ParameterInfo.Max(x => x.Length); i++) { ParameterInfo[] overloadCandidate = lastChainLink.ParameterInfo.FirstOrDefault(x => x.Length == i); if (overloadCandidate != null) { overload = overloadCandidate; break; } } if (overload != null) { var paramIndex = newCommandLength_whichParamAt_newStartIndex_numParams >> 32 & 0xff; if (overload.Length > paramIndex) { typeToPrefer = overload[paramIndex].ParameterType; } } } } } int autocompleteBoundaryIndices = FindBoundaryIndices(consoleInput, consoleInput.CaretIndex); int startIndex = autocompleteBoundaryIndices & 0xff; int length = autocompleteBoundaryIndices >> 16; string command = consoleInput.Substring(startIndex, length); AutocompletionType completionType = FindAutocompleteType(consoleInput, startIndex); if (completionType == AutocompletionType.Regular) { if (typeToPrefer == null || !string.IsNullOrWhiteSpace(command)) { FindAutocompleteForEntries(consoleInput, InstancesAndStatics, command, startIndex, isNextValue); } else { FindAutocompleteForEntries(consoleInput, GetAvailableNamesForType(typeToPrefer), command, startIndex, isNextValue); } } else // Accessor or assignment or method. { // We also need to find the value for whatever was before the type accessor. int chainEndIndex = FindPreviousLinkEndIndex(consoleInput, startIndex - 1); if (chainEndIndex < 0) { return; } Stack <string> accessorChain = FindAccessorChain(consoleInput, chainEndIndex); Member lastChainLink = FindLastChainLinkMember(accessorChain); // If no types were found, that means we are assigning a new variable. // Provide all autocomplete entries in that scenario. if (lastChainLink == null) { FindAutocompleteForEntries(consoleInput, InstancesAndStatics, command, startIndex, isNextValue); return; } switch (completionType) { case AutocompletionType.Accessor: MemberCollection autocompleteValues; if (lastChainLink.IsInstance) { _interpreter.InstanceMembers.TryGetValue(lastChainLink.Type, out autocompleteValues); } else { _interpreter.StaticMembers.TryGetValue(lastChainLink.Type, out autocompleteValues); } if (autocompleteValues == null) { break; } FindAutocompleteForEntries(consoleInput, autocompleteValues.Names, command, startIndex, isNextValue); break; case AutocompletionType.Assignment: FindAutocompleteForEntries( consoleInput, GetAvailableNamesForType(lastChainLink.Type), command, startIndex, isNextValue); break; } } }
private static void FindAutocompleteForEntries(IConsoleInput consoleInput, IList <string> autocompleteEntries, string command, int startIndex, bool isNextValue, AutocompletionType completionType) { int index = autocompleteEntries.IndexOf(x => x.Equals(command, StringComparison.Ordinal)); if (index == -1 || consoleInput.LastAutocompleteEntry == null) { consoleInput.LastAutocompleteEntry = command; } string inputEntry = consoleInput.LastAutocompleteEntry; Func <string, bool> predicate = x => x.StartsWith(inputEntry, StringComparison.Ordinal); int firstIndex = autocompleteEntries.IndexOf(predicate); if (firstIndex == -1) { return; } int lastIndex = autocompleteEntries.LastIndexOf(predicate); if (index == -1) { index = firstIndex - 1; } if (isNextValue) { index++; if (index > lastIndex) { index = firstIndex; } } else { index--; if (index < firstIndex) { index = lastIndex; } } string autocompleteValue = autocompleteEntries[index]; //if (completionType == AutocompletionType.Regular) // autocompleteValue = nameof(ExpandoWrapper.globals) + AccessorSymbol + autocompleteValue; SetAutocompleteValue(consoleInput, startIndex, autocompleteValue); }