Inheritance: NamedItemInfo, IFunctionInfo
 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;
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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);
                }
            }
        }
Beispiel #5
0
 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;
 }