private static string TruncatedCommand(ScriptSession session, string command, out string lastToken)
 {
     if (session.TryInvokeInRunningSession(ReplacementIndexHelper))
     {
         var teCmd = new Command("ScPsReplacementIndex");
         teCmd.Parameters.Add("inputScript", command);
         teCmd.Parameters.Add("cursorColumn", command.Length);
         List <object> psResult;
         if (session.TryInvokeInRunningSession(teCmd, out psResult))
         {
             var teResult = psResult.Cast <int>().FirstOrDefault();
             lastToken = command.Substring(teResult);
             return(command.Substring(0, teResult));
         }
     }
     lastToken = string.Empty;
     return(string.Empty);
 }
        public static IEnumerable <string> FindMatches(ScriptSession session, string command, bool aceResponse)
        {
            string lastToken;
            //command = command.Trim();
            var truncatedCommand = TruncatedCommand(session, command, out lastToken) ?? string.Empty;
            var truncatedLength  = truncatedCommand.Length;
            var options          = Completers;

            lastToken = lastToken.Trim();
            if (!string.IsNullOrEmpty(lastToken) && lastToken.Trim().StartsWith("["))
            {
                if (lastToken.IndexOf("]", StringComparison.Ordinal) < 0)
                {
                    return(CompleteTypes(lastToken, truncatedLength));
                }
                if (staticFuncRegex.IsMatch(lastToken))
                {
                    var matches    = staticFuncRegex.Matches(lastToken);
                    var className  = matches[0].Groups["class"].Value;
                    var methodName = matches[0].Groups["method"].Value;

                    const BindingFlags bindingFlags =
                        BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;

                    // look in acceelerators first
                    if (!className.Contains('.') && TypeAccelerators.AllAccelerators.ContainsKey(className))
                    {
                        return(GetMethodSignatures(TypeAccelerators.AllAccelerators[className], methodName, bindingFlags, truncatedLength));
                    }

                    // check the loaded assemblies
                    foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
                    {
                        try
                        {
                            var type = assembly
                                       .GetExportedTypes()
                                       .FirstOrDefault(
                                aType => aType.FullName.Equals(className, StringComparison.OrdinalIgnoreCase));
                            if (type != null)
                            {
                                return(GetMethodSignatures(type, methodName, bindingFlags, truncatedLength));
                            }
                        }
                        catch
                        {
                            // ignore on purpose
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(lastToken) && (lastToken.StartsWith("$") || lastToken.StartsWith("[")))
            {
                MatchCollection matches = null;
                var             matched = false;
                if (variableFuncRegex.IsMatch(lastToken))
                {
                    matches = variableFuncRegex.Matches(lastToken);
                    matched = true;
                }
                else if (staticExpressionRegex.IsMatch(lastToken))
                {
                    matches = staticExpressionRegex.Matches(lastToken);
                    matched = true;
                }

                if (matched)
                {
                    //var matches = variableFuncRegex.Matches(lastToken);
                    var  expression = matches[0].Groups["expression"].Value;
                    var  methodName = matches[0].Groups["method"].Value;
                    Type objectType = null;
                    try
                    {
                        if (session.TryInvokeInRunningSession(expression, out var objectValue, false))
                        {
                            if (objectValue != null && objectValue.Count > 0)
                            {
                                objectType = objectValue[0].GetType();
                            }
                        }
                    }
                    catch //(Exception ex) - variable may not be found if session does not exist
                    {
                        var varName = variableRegex.Matches(lastToken)[0].Value;
                        var message = $"Variable {varName} not found in session. Execute script first.";
                        return(new List <string> {
                            $"Signature|{message}|{truncatedLength}|{message}"
                        });
                    }
                    if (objectType != null)
                    {
                        const BindingFlags bindingFlags =
                            BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance |
                            BindingFlags.FlattenHierarchy;
                        return(GetMethodSignatures(objectType, methodName, bindingFlags, truncatedLength));
                    }
                }
            }


            session.TryInvokeInRunningSession(TabExpansionHelper);

            var teCmd = new Command("ScPsTabExpansionHelper");

            teCmd.Parameters.Add("inputScript", command);
            teCmd.Parameters.Add("cursorColumn", command.Length);
            teCmd.Parameters.Add("options", options);

            var teResult = new string[0];

            List <object> results;

            if (session.TryInvokeInRunningSession(teCmd, out results, true))
            {
                teResult = results.Cast <string>().ToArray();
            }
            var result = new List <string>();

            WrapResults(truncatedCommand, teResult, result, aceResponse);
            return(result);
        }