private IEnumerable <ParameterDoc> ParseParameters(XElement element) { List <ParameterDoc> list = new List <ParameterDoc>(); foreach (XElement paramElement in element.Elements("param")) { string name = paramElement.AttributeOrDefault("name")?.Trim(); string description = paramElement.GetInnerXml().Trim(); ParameterDoc parameterDoc = new ParameterDoc(name, description: description); list.Add(parameterDoc); } return(list); }
private List <Tuple <ParamInfo, ParameterDoc> > GetParameters(IEnumerable <ParameterInfo> parameters) { List <Tuple <ParamInfo, ParameterDoc> > result = new List <Tuple <ParamInfo, ParameterDoc> >(); foreach (ParameterInfo parameter in parameters) { ParameterKind parameterKind = default; if (parameter.IsIn) { parameterKind |= ParameterKind.In; } if (parameter.IsOut) { parameterKind |= ParameterKind.Out; } if (parameter.IsOptional) { parameterKind |= ParameterKind.Optional; } if (parameter.HasDefaultValue) { parameterKind |= ParameterKind.HasDefaultValue; } if (parameter.ParameterType.IsByRef) { parameterKind |= ParameterKind.Ref; } ParamInfo paramInfo = new ParamInfo(ConvertTypeToPopulatedType(parameter.ParameterType), parameter.Name, parameterKind); ParameterDoc parameterDoc = new ParameterDoc(parameter.Name, ConvertTypeToNameInfo(parameter.ParameterType), parameterKind); result.Add(new Tuple <ParamInfo, ParameterDoc>(paramInfo, parameterDoc)); } return(result); }
private static ICollection <ParameterDoc> GetParameterDocs(PythonFunction pf) { ParameterDoc[] res = new ParameterDoc[pf.ArgNames.Length]; for (int i = 0; i < res.Length; i++) { ParameterFlags flags = ParameterFlags.None; if (i == pf.ExpandDictPosition) { flags |= ParameterFlags.ParamsDict; } else if (i == pf.ExpandListPosition) { flags |= ParameterFlags.ParamsArray; } res[i] = new ParameterDoc( pf.ArgNames[i], flags ); } return(res); }
/// <summary> /// Creates a DLR OverloadDoc object which describes information about this overload. /// </summary> /// <param name="info">The method to document</param> /// <param name="name">The name of the method if it should override the name in the MethodBase</param> /// <param name="endParamSkip">Parameters to skip at the end - used for removing the value on a setter method</param> /// <param name="includeSelf">true to include self on instance methods</param> public static OverloadDoc GetOverloadDoc(MethodBase info, string name, int endParamSkip, bool includeSelf) { string summary = null, returns = null; List <KeyValuePair <string, string> > parameters = null; #if FEATURE_XMLDOC GetXmlDoc(info, out summary, out returns, out parameters); #endif StringBuilder retType = new StringBuilder(); int returnCount = 0; MethodInfo mi = info as MethodInfo; if (mi != null) { if (mi.ReturnType != typeof(void)) { retType.Append(GetPythonTypeName(mi.ReturnType)); returnCount++; try { var typeAttrs = mi.ReturnParameter.GetCustomAttributes(typeof(SequenceTypeInfoAttribute), true); if (typeAttrs.Any()) { retType.Append(" (of "); SequenceTypeInfoAttribute typeAttr = (SequenceTypeInfoAttribute)typeAttrs.First(); for (int curTypeAttr = 0; curTypeAttr < typeAttr.Types.Count; curTypeAttr++) { if (curTypeAttr != 0) { retType.Append(", "); } retType.Append(GetPythonTypeName(typeAttr.Types[curTypeAttr])); } retType.Append(")"); } } catch (IndexOutOfRangeException) { } // swallow bug in .NET Core try { var dictTypeAttrs = mi.ReturnParameter.GetCustomAttributes(typeof(DictionaryTypeInfoAttribute), true); if (dictTypeAttrs.Any()) { var dictTypeAttr = (DictionaryTypeInfoAttribute)dictTypeAttrs.First(); retType.Append(String.Format(" (of {0} to {1})", GetPythonTypeName(dictTypeAttr.KeyType), GetPythonTypeName(dictTypeAttr.ValueType))); } } catch (IndexOutOfRangeException) { } // swallow bug in .NET Core } if (name == null) { var hashIndex = mi.Name.IndexOf('#'); if (hashIndex == -1) { name = mi.Name; } else { name = mi.Name.Substring(0, hashIndex); } } } else if (name == null) { name = "__new__"; } // For generic methods display either type parameters (for unbound methods) or // type arguments (for bound ones). if (mi != null && mi.IsGenericMethod) { Type[] typePars = mi.GetGenericArguments(); bool unbound = mi.ContainsGenericParameters; StringBuilder tmp = new StringBuilder(); tmp.Append(name); tmp.Append("["); if (typePars.Length > 1) { tmp.Append("("); } bool insertComma = false; foreach (Type t in typePars) { if (insertComma) { tmp.Append(", "); } if (unbound) { tmp.Append(t.Name); } else { tmp.Append(GetPythonTypeName(t)); } insertComma = true; } if (typePars.Length > 1) { tmp.Append(")"); } tmp.Append("]"); name = tmp.ToString(); } List <ParameterDoc> paramDoc = new List <ParameterDoc>(); if (mi == null) { if (name == "__new__") { // constructor, auto-insert cls paramDoc.Add(new ParameterDoc("cls", "type")); } } else if (!mi.IsStatic && includeSelf) { paramDoc.Add(new ParameterDoc("self", GetPythonTypeName(mi.DeclaringType))); } ParameterInfo[] pis = info.GetParameters(); for (int i = 0; i < pis.Length - endParamSkip; i++) { ParameterInfo pi = pis[i]; if (i == 0 && pi.ParameterType == typeof(CodeContext)) { // hide CodeContext parameters continue; } if ((pi.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out || pi.ParameterType.IsByRef) { if (returnCount == 1) { retType.Insert(0, "("); } if (returnCount != 0) { retType.Append(", "); } returnCount++; retType.Append(GetPythonTypeName(pi.ParameterType)); if ((pi.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out) { continue; } } ParameterFlags flags = ParameterFlags.None; if (pi.IsDefined(typeof(ParamArrayAttribute), false)) { flags |= ParameterFlags.ParamsArray; } else if (pi.IsDefined(typeof(ParamDictionaryAttribute), false)) { flags |= ParameterFlags.ParamsDict; } string paramDocString = null; if (parameters != null) { foreach (var paramXmlDoc in parameters) { if (paramXmlDoc.Key == pi.Name) { paramDocString = paramXmlDoc.Value; break; } } } paramDoc.Add( new ParameterDoc( pi.Name ?? "", // manufactured methods, such as string[].ctor(int) can have no parameter names. pi.ParameterType.IsGenericParameter ? pi.ParameterType.Name : GetPythonTypeName(pi.ParameterType), paramDocString, flags ) ); } if (returnCount > 1) { retType.Append(')'); } ParameterDoc retDoc = new ParameterDoc(String.Empty, retType.ToString(), returns); return(new OverloadDoc( name, summary, paramDoc, retDoc )); }
public static void Main(string[] args) { try { // load .dll files in the current directory to foreach (var file in Directory.GetFiles(Environment.CurrentDirectory, "*", SearchOption.AllDirectories)) { if (file.ToLowerInvariant().EndsWith(".dll")) { Assembly.LoadFile(file); } } foreach (var file in Directory.GetFiles(Environment.CurrentDirectory, "*", SearchOption.AllDirectories)) { if (file.ToLowerInvariant().EndsWith(".xml")) { string xmlStr = File.ReadAllText(file); xmlStr = Regex.Replace(xmlStr, "<see cref=\"[A-Z?]:(.*)\" \\/>", m => "<a href=\"#" + m.Groups[1].Value.ToLower().Replace('.', '-') + "\">" + m.Groups[1].Value.Split('.').Last() + "</a>" ); xmlStr = Regex.Replace(xmlStr, @"<(c|code)>([^<])*<\/(c|code)>", m => "<" + m.Groups[1].Value + ">" + m.Groups[2].Captures.Join() + "</" + m.Groups[1].Value + ">" ); using (var stream = xmlStr.ToStream()) { // TODO: Add reflection stuff, to: // * determine if properties has setters or only getters using (var xml = System.Xml.XmlReader.Create(stream)) { while (xml.Read()) { if (xml.IsStartElement()) { BaseDoc CurrentDoc = null; switch (xml.Name) { case "assembly": CurrentAssembly = new AssemblyDoc(); CurrentDoc = CurrentAssembly; break; case "name": xml.Read(); CurrentAssembly.Name = xml.Value; reflectedAssembly = AppDomain.CurrentDomain.GetAssemblies().ToList().First(a => a.GetName().Name == xml.Value); break; case "member": var memberName = xml["name"]; char type = memberName[0]; if (memberName.Contains("Hooks")) { PreviousDoc = null; break; } switch (type) { case 'T': CurrentDoc = new TypeDoc(CurrentAssembly); CurrentType = CurrentDoc; reflectedType = reflectedAssembly.GetType(memberName.Substring(2)); break; case 'P': case 'F': if (CurrentType == null || !memberName.Contains(CurrentType.Name.Substring(2))) { string typename = memberName.GetTypeName(); CurrentType = new TypeDoc(CurrentAssembly) { Name = typename }; reflectedType = reflectedAssembly.GetType(typename); } // if type == p => add property documentation else => add field doc. CurrentDoc = type == 'P' ? (new PropertyDoc(CurrentType as TypeDoc) { Name = memberName.Substring(2), Type = (from pinfo in reflectedType.GetProperties() where pinfo.Name == memberName.GetMemberName() select pinfo.PropertyType).FirstOrDefault() } as BaseDoc) : (new FieldDoc(CurrentType as TypeDoc) { Name = memberName.Substring(2), Type = (from finfo in reflectedType.GetFields() where finfo.Name == memberName.GetMemberName() select finfo.FieldType).FirstOrDefault() } as BaseDoc); break; case 'M': // check if the method is a method of the _current_ type, if it's not then it means the type of this method is not _documented_ // so we add an empty doc for it here if (CurrentType == null || !memberName.Contains(CurrentType.Name.Substring(2))) { string typename = memberName.GetTypeName(); CurrentType = new TypeDoc(CurrentAssembly) { Name = typename }; reflectedType = reflectedAssembly.GetType(typename); } reflectedMethodParams = new List <Type>(); string methodname = memberName.GetMemberName(); string paramtypes = Regex.Match(memberName, "\\(([\\.,A-z0-9])*\\)").Groups[1].Captures.Join(); foreach (var paramtype in paramtypes.Split(',')) { Type typ = null; if (!TryFindType(paramtype, out typ)) { var paramtype2 = Regex.Replace(paramtype, "(.*)\\.([A-z]*)$", "$1+$2"); TryFindType(paramtype2, out typ); } if (typ != null) { reflectedMethodParams.Add(typ); } } if (!methodname.Contains('#')) { reflectedMethod = reflectedType.GetMethod(methodname, reflectedMethodParams.ToArray()); } else { reflectedMethod = reflectedType.GetConstructor(reflectedMethodParams.ToArray()); } // the method's name for constructors is #ctor, lets change that to the name of the Type if (memberName.Contains("#ctor")) { CurrentDoc = new ConstructorDoc(CurrentType as TypeDoc); CurrentDoc.Name = memberName.Replace("#ctor", Regex.Match(memberName, ".([A-z]+).#").Groups[1].Value).Substring(2); CurrentDoc.Name = CurrentDoc.Name.Substring(0, CurrentDoc.Name.IndexOf("(")); } else { CurrentDoc = new MethodDoc(CurrentType as TypeDoc); } CurrentMethod = CurrentDoc; currentParam = 0; if (reflectedMethod is MethodInfo) { CurrentMethod["ReturnType"] = (reflectedMethod as MethodInfo).ReturnType; } else { CurrentMethod["ReturnType"] = reflectedType; } break; } if (CurrentDoc.Name == null) { if (memberName.Contains("(")) { CurrentDoc.Name = memberName.Substring(2, memberName.IndexOf("(") - 2); } else { CurrentDoc.Name = memberName.Substring(2); } } break; case "summary": xml.Read(); if (PreviousDoc != null) { PreviousDoc["Summary"] = xml.Value.Trim(); } break; case "param": string name = xml["name"]; xml.Read(); CurrentDoc = new ParameterDoc(CurrentMethod) { Name = name, Summary = xml.Value, Type = reflectedMethodParams[currentParam] }; currentParam++; break; case "csharp": case "javascript": case "python": case "lua": if (PreviousDoc is TypeDoc) { var cdoc = PreviousDoc as TypeDoc; var lang = xml.Name; xml.Read(); cdoc.CodeExamples.Add(new CodeExample { Code = xml.Value, Language = (Language)Enum.Parse(typeof(Language), lang) }); } else if (PreviousDoc is MethodDoc) { var cdoc = PreviousDoc as MethodDoc; var lang = xml.Name; xml.Read(); cdoc.CodeExamples.Add(new CodeExample { Code = xml.Value, Language = (Language)Enum.Parse(typeof(Language), lang) }); } break; case "value": xml.Read(); PreviousDoc["defaultValue"] = xml.Value; break; } if (CurrentDoc != null) { PreviousDoc = CurrentDoc; } } } } #if DEBUG Console.WriteLine("CurrentAssembly is: " + Environment.NewLine + CurrentAssembly); #endif CurrentAssembly.ToFile(); } } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.WriteLine(ex.StackTrace); } }