public static FinalizedResponse FuncName_AC(TokLinePlanB <PTok> orig_TL, TokLinePlanB <PTok> .CPosC CPos, MGRX.FuncNameNodeRX funcNameNodeRX, Responder RESP) { Func <PTokE, bool> ON = tokE => { var tok = CPos.insideof_tok; if (tok == null) { return(false); } return(tok.E == tokE); }; Func <PTokE, bool> LADJ = tokE => { var tok = CPos.immediateLAdj_tok; if (tok == null) { return(false); } return(tok.E == tokE); }; Func <TokLinePlanB <PTok>, PTokBase[]> SER = tokLine => tokLine.Serialize <PTokBase>(onTok: _ => _, onWS: i => new PTokWhitespace { len = i }).ToArray(); Type hosting_type; try { hosting_type = funcNameNodeRX.AC_FuncHostingType_Callback(); if (hosting_type == null) { throw new Exception("hosting type null"); } } catch (Exception e) { return(RESP.NoAC(e.Message)); } string name_fragment; if (LADJ(PTokE.CS_name)) { name_fragment = CPos.immediateLAdj_tok.pay; MethodInfo [] raw_suggs_MI = SGA.MethodAC(hosting_type, name_fragment, (funcNameNodeRX.parent as MG.FunCallNode).isStatic); if (raw_suggs_MI.Length == 0) { return(RESP.NoAC("no matching alternatives")); } string new_prefix = SGA.LongestCommonPrefix(raw_suggs_MI.Select(mi => mi.Name).ToArray()); if (new_prefix.Length > name_fragment.Length) { PTok new_token = new PTok { pay = new_prefix, E = PTokE.CS_name }; orig_TL.ReplaceTok(CPos.immediateLAdj_tok, new_token); var nu_Cpos = orig_TL.CPosAtEndOfTok(new_token); return(RESP.FuncACWithSubst(raw_suggs_MI, SER(orig_TL), nu_Cpos.StringPos())); } else { return(RESP.FuncACNoSubst(raw_suggs_MI)); } } else if (LADJ(PTokE.OP_backslash)) { // no check for whether the curser is under a CS_name token , like so // [>> [_] :Tyname\Funcname] // _ // in this case junk gets substituted left of `Funcname` // idc rn - there are bigger fish to fry MethodInfo [] raw_suggs_MI = SGA.MethodAC(hosting_type, "", (funcNameNodeRX.parent as MG.FunCallNode).isStatic); if (raw_suggs_MI.Length == 0) { return(RESP.NoAC("no matching alternatives")); } string new_prefix = SGA.LongestCommonPrefix(raw_suggs_MI.Select(mi => mi.Name).ToArray()); if (new_prefix.Length > 0) { var nu_tok = new PTok { E = PTokE.CS_name, pay = new_prefix }; orig_TL.InsertTokAfterNode(CPos.N, nu_tok); // this is the precise behaviour of IsertAfterCPos when its not over whitespace var nu_Cpos = orig_TL.CPosAtEndOfTok(nu_tok); var nu_offs = nu_Cpos.StringPos(); return(RESP.FuncACWithSubst(raw_suggs_MI, SER(orig_TL), nu_offs)); } else { return(RESP.FuncACNoSubst(raw_suggs_MI)); } } else { return(RESP.NoAC("useless position")); } // currrently only doing ON( CS_name ) }
public static FinalizedResponse Type_AC(TokLinePlanB <PTok> orig_TL, TokLinePlanB <PTok> .CPosC CPos, NamedNode n, Responder RESP) { Func <PTokE, bool> ON = tokE => { var tok = CPos.insideof_tok; if (tok == null) { return(false); } return(tok.E == tokE); }; Func <PTokE, bool> AFTER = tokE => { var tok = CPos.immediateLAdj_tok; if (tok == null) { return(false); } return(tok.E == tokE); }; MGRX.TypeNameNodeRX TNRX_node = (MGRX.TypeNameNodeRX)n; if (ON(PTokE.CS_name) || AFTER(PTokE.CS_name)) { PTok targetTok = null; if ((CPos.insideof_tok != null) && (CPos.insideof_tok.E == PTokE.CS_name)) { targetTok = CPos.insideof_tok; } else { targetTok = CPos.immediateLAdj_tok; // todo: unsafe } var Largs = new List <string>(); foreach (var tok in TNRX_node.nameToks) { Largs.Add(tok.pay); if (tok == targetTok) { break; } } // targetTok might not be the last in sequence - collect all CS_names upto and including string prefix = null; var type_alts = SGA.QTN_AC(Largs.ToArray(), out prefix); if (prefix.Length > targetTok.pay.Length) { var new_tok = new PTok { E = PTokE.CS_name, pay = prefix }; orig_TL.ReplaceTok(targetTok, new_tok); return(RESP.TypeACWithSubst(type_alts, SerializeTokLine(orig_TL), orig_TL.CPosAtEndOfTok(new_tok).StringPos())); } else { return(RESP.TypeACNoSubst(type_alts)); } } else if (CPos.immediateLAdj_tok == null) // abuse this as "on whitespace or EOL" - probably incomplete // problem : // TokLine was not designed with the possibility in mind that Tokens change without notice // thus: insert dummy token | do stuff | replace dummy token with the final one { PTok placeholderTok = new PTok { E = PTokE.CS_name, pay = "" }; var placeholderCpos = orig_TL.InsertAfterCPos(CPos, placeholderTok); // extra evil - accessing internal Node structure directly - wo way to iterate from CPosC yet PTok delim = null; // non whitespace token to the left of insertion point var cand = placeholderCpos.N.left; while (true) { if (cand is TokLinePlanB <PTok> .NodeTok) { delim = cand.tok; break; } cand = cand.left; } var Largs = new List <string>(); foreach (var tok in TNRX_node.Leafs().Where(N => N is MG.TermNode).Select(MG.TermTok)) // have to iterate over all terminals instead of just CS_names , because delimiter might be some other kind { if (tok.E == PTokE.CS_name) { Largs.Add(tok.pay); } if (tok == delim) { break; // collect inclusive delimiter } } Largs.Add(""); // last arg to SuggTree is an empty prefix string prefix; var alts = SGA.QTN_AC(Largs.ToArray(), out prefix); if (prefix.Length > 0) { return(RESP.TypeACNoSubst(alts)); } else { var final_tok = new PTok { E = PTokE.CS_name, pay = prefix }; orig_TL.ReplaceTok(placeholderTok, final_tok); return(RESP.TypeACWithSubst(alts, SerializeTokLine(orig_TL), orig_TL.CPosAtEndOfTok(final_tok).StringPos())); } } return(RESP.NoAC("kind of type AC not implemented atm")); }