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 static IReadOnlyList <IFunctionInfo> ParseFunctions(RdParseContext context) { IReadOnlyList <ISignatureInfo> signatureInfos = null; IReadOnlyDictionary <string, string> argumentDescriptions = null; var aliases = new List <string>(); string functionDescription = null; // Description is normally one for all similar functions bool isInternal = false; string returnValue = null; string primaryName = null; while (!context.Tokens.IsEndOfStream() && (functionDescription == null || argumentDescriptions == null || signatureInfos == null || returnValue == 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 if (context.IsAtKeyword(@"\alias")) { var alias = RdText.GetText(context); if (!string.IsNullOrWhiteSpace(alias)) { aliases.Add(alias); } } else if (primaryName == null && context.IsAtKeyword(@"\name")) { primaryName = RdText.GetText(context); } else { context.Tokens.Advance(2); } } else { context.Tokens.MoveToNextToken(); } } // Merge descriptions into signatures if (argumentDescriptions != null && signatureInfos != null) { foreach (ISignatureInfo sigInfo in signatureInfos) { // Add missing arguments from the \arguments{} section foreach (var arg in sigInfo.Arguments) { string description; if (argumentDescriptions.TryGetValue(arg.Name, out description)) { ((NamedItemInfo)arg).Description = description ?? string.Empty; } } } } // Merge signatures into function infos var functionInfos = new Dictionary <string, FunctionInfo>(); if (signatureInfos != null) { var 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 = CreateFunctionInfo(sigInfo.FunctionName, functionDescription, returnValue, isInternal); functionInfos[sigInfo.FunctionName] = functionInfo; // 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); } } // Propage to aliases if (!string.IsNullOrWhiteSpace(primaryName)) { FunctionInfo functionInfo; if (functionInfos.TryGetValue(primaryName, out functionInfo)) { foreach (var alias in aliases) { if (!functionInfos.ContainsKey(alias)) { functionInfos[alias] = new FunctionInfo(alias, functionInfo); } } } } return(functionInfos.Values.ToList()); }