public static IFunctionInfo MakeFunctionInfo(this IFunctionDefinition fd, string functionName) { if (fd != null) { var fi = new FunctionInfo(functionName); fi.Signatures = new ISignatureInfo[] { fd.MakeSignature(functionName) }; return fi; } return null; }
private static bool LoadFunctions(ConcurrentDictionary<string, string> functionToPackageMap) { try { // Function data format: // 1 if function is internal, 0 otherwise // Function description (one long line) // Function signatures (one per line) // an empty line // argument descriptions (one per line) in a form // argument_name: description foreach (string functionName in functionToPackageMap.Keys) { string packageName = functionToPackageMap[functionName]; string packageFolderName = Path.Combine(RtvsDataPath, packageName); string signaturesFileName = Path.Combine(packageFolderName, functionName + ".fd"); using (StreamReader sr = new StreamReader(signaturesFileName)) { bool isInternal = ReadInternal(sr); string description = sr.ReadLine().Trim(); List<string> signatureStrings = ReadSignatures(sr); Dictionary<string, string> arguments = ReadArguments(sr); List<ISignatureInfo> signatureInfos = new List<ISignatureInfo>(); foreach (string s in signatureStrings) { SignatureInfo info = RdFunctionSignature.ParseSignature(s); signatureInfos.Add(info); } foreach (SignatureInfo sig in signatureInfos) { foreach(ArgumentInfo arg in sig.Arguments) { string argDescription; if (arguments.TryGetValue(arg.Name, out argDescription)) { arg.Description = argDescription; } } } FunctionInfo functionInfo = new FunctionInfo(functionName, description); functionInfo.IsInternal = isInternal; functionInfo.Signatures = signatureInfos; } } } catch (IOException) { return false; } return true; }
private static IReadOnlyList<IFunctionInfo> ParseFunctions(RdParseContext context) { IReadOnlyList<ISignatureInfo> signatureInfos = null; IReadOnlyDictionary<string, string> argumentDescriptions = null; string functionDescription = null; // Description is normally one for all similar functions bool isInternal = false; string returnValue = null; while (!context.Tokens.IsEndOfStream() && argumentDescriptions == null) { RdToken token = context.Tokens.CurrentToken; if (context.IsAtKeywordWithParameters()) { if (string.IsNullOrEmpty(functionDescription) && context.IsAtKeyword(@"\description")) { functionDescription = RdText.GetText(context); } else if (context.IsAtKeyword(@"\keyword")) { string keyword = RdText.GetText(context); if (!string.IsNullOrEmpty(keyword) && keyword.Contains("internal")) { isInternal = true; } } else if (string.IsNullOrEmpty(returnValue) && context.IsAtKeyword(@"\value")) { returnValue = RdText.GetText(context); } else if (argumentDescriptions == null && context.IsAtKeyword(@"\arguments")) { // Extract arguments and their descriptions argumentDescriptions = RdArgumentDescription.ExtractArgumentDecriptions(context); } else if (signatureInfos == null && context.IsAtKeyword(@"\usage")) { // Extract signatures with function names signatureInfos = RdFunctionSignature.ExtractSignatures(context); } else { context.Tokens.Advance(2); } } else { context.Tokens.MoveToNextToken(); } } // Merge descriptions into signatures. Add all arguments // listed in the \arguments{} section since function signature // does not always list all possible arguments. if (argumentDescriptions != null && signatureInfos != null) { foreach (ISignatureInfo sigInfo in signatureInfos) { // Add missing arguments from the \arguments{} section foreach (string name in argumentDescriptions.Keys) { // TODO: do we need HashSet here instead? Generally arguments // list is relatively short, about 10 items on average. if (sigInfo.Arguments.FirstOrDefault(x => x.Name.Equals(name)) == null) { sigInfo.Arguments.Add(new ArgumentInfo(name)); } } // Relocate ..., if any, to the end var ellipsisArgument = sigInfo.Arguments.FirstOrDefault(x => x.IsEllipsis); if (ellipsisArgument != null) { int index = sigInfo.Arguments.IndexOf(ellipsisArgument); sigInfo.Arguments.RemoveAt(index); sigInfo.Arguments.Add(ellipsisArgument); } // Add description if it is not there yet foreach (var arg in sigInfo.Arguments.Where(x => string.IsNullOrEmpty(x.Description))) { string description; if (argumentDescriptions.TryGetValue(arg.Name, out description)) { ((NamedItemInfo)arg).Description = description ?? string.Empty; } } } } // Merge signatures into function infos Dictionary<string, FunctionInfo> functionInfos = new Dictionary<string, FunctionInfo>(); if (signatureInfos != null) { Dictionary<string, List<ISignatureInfo>> functionSignatures = new Dictionary<string, List<ISignatureInfo>>(); foreach (ISignatureInfo sigInfo in signatureInfos) { FunctionInfo functionInfo; List<ISignatureInfo> sigList; if (!functionInfos.TryGetValue(sigInfo.FunctionName, out functionInfo)) { // Create function info functionInfo = new FunctionInfo(sigInfo.FunctionName, functionDescription); functionInfos[sigInfo.FunctionName] = functionInfo; functionInfo.IsInternal = isInternal; functionInfo.ReturnValue = returnValue; // Create list of signatures for this function sigList = new List<ISignatureInfo>(); functionSignatures[sigInfo.FunctionName] = sigList; functionInfo.Signatures = sigList; } else { sigList = functionSignatures[sigInfo.FunctionName]; } sigList.Add(sigInfo); } } return functionInfos.Values.ToList(); }
private void UpdateIndex(string functionName, string packageName, string rdData) { IReadOnlyList<IFunctionInfo> functionInfos = GetFunctionInfosFromRd(rdData); foreach (IFunctionInfo info in functionInfos) { _functionToInfoMap[GetQualifiedName(info.Name, packageName)] = info; } var qualifiedName = GetQualifiedName(functionName, packageName); if (!_functionToInfoMap.ContainsKey(qualifiedName)) { if (functionInfos.Count > 0) { // RD doesn't contain the requested function. // e.g. as.Date.character has RD for as.Date but not itself // without its own named info, this will request indefinitely many times // as workaround, add the first info with functionName _functionToInfoMap[qualifiedName] = functionInfos[0]; } else { // Add stub function info here to prevent subsequent calls // for the same function as we already know the call will fail. _functionToInfoMap[qualifiedName] = new FunctionInfo(functionName); } } }
private static FunctionInfo CreateFunctionInfo(string functionName, string functionDescription, string returnValue, bool isInternal) { var functionInfo = new FunctionInfo(functionName, functionDescription); functionInfo.IsInternal = isInternal; functionInfo.ReturnValue = returnValue; return functionInfo; }