private CodeDocMethod ConvertToModel(MethodBase methodBase, CodeDocMemberDetailLevel detailLevel, ICodeDocMemberDataProvider extraMemberDataProvider = null) { Contract.Requires(methodBase != null); Contract.Ensures(Contract.Result<CodeDocMethod>() != null); Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().ShortName)); Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().FullName)); Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().Title)); Contract.Ensures(Contract.Result<CodeDocMethod>().Title == Contract.Result<CodeDocMethod>().ShortName); Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<CodeDocMethod>().SubTitle)); var includeExceptions = detailLevel != CodeDocMemberDetailLevel.Minimum; var appendXmlDoc = detailLevel.HasFlag(CodeDocMemberDetailLevel.Summary) || detailLevel.HasFlag(CodeDocMemberDetailLevel.AdditionalContents); var provideXmlDoc = includeExceptions || detailLevel != CodeDocMemberDetailLevel.Minimum; var includeInheritance = detailLevel.HasFlag(CodeDocMemberDetailLevel.Inheritance); var includeParameters = detailLevel != CodeDocMemberDetailLevel.Minimum; var methodInfo = methodBase as MethodInfo; var methodCRef = GetCRefIdentifier(methodBase); var model = new CodeDocMethod(methodCRef); model.Uri = GetUri(methodBase); var memberDataProvider = new CodeDocMemberInfoProvider<MethodBase>(methodBase); if (provideXmlDoc) { var xmlDocs = XmlDocs.GetMember(methodCRef.FullCRef); if (xmlDocs != null) memberDataProvider.Add(new CodeDocMemberXmlDataProvider(xmlDocs)); } if (extraMemberDataProvider != null) memberDataProvider.Add(extraMemberDataProvider); if (includeInheritance && methodInfo != null) { var baseDefinition = methodInfo.FindNextAncestor(); if (baseDefinition != null) { var baseDefinitionModel = GetOnly(GetCRefIdentifier(baseDefinition), detailLevel); if (baseDefinitionModel != null) memberDataProvider.Add(new CodeDocMemberDataProvider(baseDefinitionModel)); } } if (appendXmlDoc) ApplyContentXmlDocs(model, memberDataProvider); model.ExternalVisibility = memberDataProvider.ExternalVisibility ?? ExternalVisibilityKind.Public; model.ShortName = RegularTypeDisplayNameOverlay.GetDisplayName(methodBase); model.FullName = FullTypeDisplayNameOverlay.GetDisplayName(methodBase); model.Title = model.ShortName; Contract.Assume(methodBase.DeclaringType != null); model.NamespaceName = methodBase.DeclaringType.Namespace; if (includeParameters) { model.Parameters = Array.ConvertAll( methodBase.GetParameters(), p => CreateArgument(p, memberDataProvider)); if (methodInfo != null && methodInfo.ReturnParameter != null && methodInfo.ReturnType != typeof (void)) model.Return = CreateReturn(methodInfo.ReturnParameter, memberDataProvider); } if (methodBase.IsConstructor) model.SubTitle = "Constructor"; else if (model.Parameters != null && model.Parameters.Count == 1 && model.HasReturn && CSharpOperatorNameSymbolMap.IsConversionOperatorMethodName(methodBase.Name)) { model.SubTitle = "Conversion"; string conversionOperationName; if (methodBase.Name.EndsWith("Explicit", StringComparison.OrdinalIgnoreCase)) conversionOperationName = "Explicit"; else if (methodBase.Name.EndsWith("Implicit", StringComparison.OrdinalIgnoreCase)) conversionOperationName = "Implicit"; else conversionOperationName = String.Empty; var conversionParameterPart = String.Concat( model.Parameters[0].ParameterType.ShortName, " to ", model.Return.ParameterType.ShortName); model.ShortName = String.IsNullOrEmpty(conversionOperationName) ? conversionParameterPart : String.Concat(conversionOperationName, ' ', conversionParameterPart); model.Title = model.ShortName; } else if (methodBase.IsOperatorOverload()) model.SubTitle = "Operator"; else model.SubTitle = "Method"; Contract.Assume(methodBase.DeclaringType != null); model.Namespace = GetOrCreateNamespaceByName(methodBase.DeclaringType.Namespace); model.Assembly = GetCodeDocAssembly(methodBase.DeclaringType.Assembly); model.DeclaringType = GetOrConvert(methodBase.DeclaringType, CodeDocMemberDetailLevel.Minimum); model.IsOperatorOverload = methodBase.IsOperatorOverload(); model.IsExtensionMethod = methodBase.IsExtensionMethod(); model.IsSealed = methodBase.IsSealed(); model.IsStatic = memberDataProvider.IsStatic.GetValueOrDefault(); model.IsObsolete = memberDataProvider.IsObsolete.GetValueOrDefault(); model.IsPure = memberDataProvider.IsPure.GetValueOrDefault(); if (methodBase.DeclaringType != null && !methodBase.DeclaringType.IsInterface) { if (methodBase.IsAbstract) model.IsAbstract = true; else if (methodBase.IsVirtual && !methodBase.IsFinal && methodBase.Attributes.HasFlag(MethodAttributes.NewSlot)) model.IsVirtual = true; } if (includeExceptions){ if (memberDataProvider.HasExceptions) model.Exceptions = CreateExceptionModels(memberDataProvider.GetExceptions()).ToArray(); if (memberDataProvider.HasEnsures) model.Ensures = memberDataProvider.GetEnsures().ToArray(); if (memberDataProvider.HasRequires) model.Requires = memberDataProvider.GetRequires().ToArray(); } if (includeParameters && methodBase.IsGenericMethod) { var genericDefinition = methodBase.IsGenericMethodDefinition ? methodBase : methodInfo == null ? null : methodInfo.GetGenericMethodDefinition(); if (genericDefinition != null) { var genericArguments = genericDefinition.GetGenericArguments(); if (genericArguments.Length > 0) { model.GenericParameters = CreateGenericTypeParameters( genericArguments, memberDataProvider); } } } return model; }
protected CodeDocMethod ToMethodModel(ICodeDocMember member) { if (member == null) return null; if (member is CodeDocMethod) return (CodeDocMethod)member; var methodModel = new CodeDocMethod(member.CRef.WithTargetType("M")); var simpleMember = member as CodeDocSimpleMember; if (simpleMember != null) CopySimpleMemberAttributes(methodModel, simpleMember); return methodModel; }
/// <summary> /// Generates a model that is extracted from MTPS data. /// </summary> /// <param name="cRef">The code reference to search for.</param> /// <param name="searchContext">The search context for locating related items.</param> /// <param name="detailLevel">The desired detail level of the generated model.</param> /// <returns>A code doc member model if found.</returns> public ICodeDocMember GetMemberModel(CRefIdentifier cRef, CodeDocRepositorySearchContext searchContext = null, CodeDocMemberDetailLevel detailLevel = CodeDocMemberDetailLevel.Full) { if(cRef == null) throw new ArgumentNullException("cRef"); Contract.EndContractBlock(); var stopwatch = new Stopwatch(); stopwatch.Start(); var tocResults = SearchToc(cRef.FullCRef); var bestTocResult = tocResults.FirstOrDefault(); stopwatch.Stop(); Debug.WriteLine("Search for {0} returned in {1}", cRef, stopwatch.Elapsed); if (bestTocResult == null) return null; Uri uri; if (!Uri.TryCreate(GetUrl(bestTocResult), UriKind.Absolute, out uri)) uri = cRef.ToUri(); CodeDocSimpleMember model = null; if (detailLevel != CodeDocMemberDetailLevel.Minimum) { var contentXml = GetContent(bestTocResult.ContentId); if (contentXml != null) { bool? isSealed = null; bool? isValueType = null; bool? isReferenceType = null; bool? isEnum = null; bool? isVirtual = null; bool? isAbstract = null; bool? isMethod = null; ExternalVisibilityKind? visibility = null; var titleDiv = contentXml.GetElementsByTagName("div") .OfType<XmlElement>() .FirstOrDefault(x => "TITLE".Equals(x.GetAttribute("class"), StringComparison.OrdinalIgnoreCase)); if (titleDiv != null) { var innerTitleText = titleDiv.InnerText.Trim(); if (innerTitleText.EndsWith("Method", StringComparison.OrdinalIgnoreCase)) { isMethod = true; } } var syntaxElement = contentXml.GetElementsByTagName("mtps:CollapsibleArea") .OfType<XmlElement>() .FirstOrDefault(x => "SYNTAX".Equals(x.GetAttribute("Title"), StringComparison.OrdinalIgnoreCase)); var codeSnippets = syntaxElement.GetElementsByTagName("mtps:CodeSnippet").OfType<XmlElement>().ToList(); foreach (var snippet in codeSnippets) { var inputSpans = snippet.GetElementsByTagName("span") .OfType<XmlElement>() .Where(e => e.GetAttribute("class") == "input") .ToList(); if (snippet.GetAttribute("Language") == "CSharp") { foreach (var inputSpan in inputSpans) { var innerText = inputSpan.InnerText; if ("PUBLIC".Equals(innerText, StringComparison.OrdinalIgnoreCase)) visibility = ExternalVisibilityKind.Public; else if ("PROTECTED".Equals(innerText, StringComparison.OrdinalIgnoreCase)) visibility = ExternalVisibilityKind.Protected; else if ("SEALED".Equals(innerText, StringComparison.OrdinalIgnoreCase)) isSealed = true; else if ("CLASS".Equals(innerText, StringComparison.OrdinalIgnoreCase)) isReferenceType = true; else if ("STRUCT".Equals(innerText, StringComparison.OrdinalIgnoreCase)) isValueType = true; else if ("ENUM".Equals(innerText, StringComparison.OrdinalIgnoreCase)) isEnum = true; else if ("VIRTUAL".Equals(innerText, StringComparison.OrdinalIgnoreCase)) isVirtual = true; else if ("ABSTRACT".Equals(innerText, StringComparison.OrdinalIgnoreCase)) isAbstract = true; } } } if (model == null) { if (isReferenceType ?? isValueType ?? isEnum ?? false) { var typeModel = new CodeDocType(cRef); typeModel.IsSealed = isSealed; typeModel.IsValueType = isValueType; typeModel.IsEnum = isEnum; model = typeModel; } else if (isMethod ?? false) { var methodModel = new CodeDocMethod(cRef); methodModel.IsSealed = isSealed; methodModel.IsVirtual = isVirtual; methodModel.IsAbstract = isAbstract; model = methodModel; } else { model = new CodeDocSimpleMember(cRef); } model.ExternalVisibility = visibility ?? ExternalVisibilityKind.Hidden; } XmlNode summaryElement = contentXml.GetElementsByTagName("div") .OfType<XmlElement>() .FirstOrDefault(x => String.Equals(x.GetAttribute("class"), "summary", StringComparison.OrdinalIgnoreCase)); if (summaryElement != null) { if (summaryElement.ChildNodes.Count == 1 && summaryElement.ChildNodes[0].Name == "p") { // unwrap the lone p tag. summaryElement = summaryElement.ChildNodes[0]; } var summaryXmlDoc = XmlDocParser.Default.Parse(summaryElement); model.SummaryContents = summaryXmlDoc.Children; } } } if (model == null) model = new CodeDocSimpleMember(cRef); if(model.ExternalVisibility == ExternalVisibilityKind.Hidden) model.ExternalVisibility = ExternalVisibilityKind.Public; model.Uri = uri; model.FullName = bestTocResult.GetFullName(); int lastTitleSpaceIndex = bestTocResult.Title.LastIndexOf(' '); if (lastTitleSpaceIndex >= 0) { model.Title = bestTocResult.Title.Substring(0, lastTitleSpaceIndex); model.SubTitle = bestTocResult.Title.Substring(lastTitleSpaceIndex + 1); } else { model.Title = bestTocResult.Title; model.SubTitle = String.Empty; } model.ShortName = model.Title; if (String.IsNullOrEmpty(model.NamespaceName)) { MtpsNodeCore namespaceNode = bestTocResult; while (namespaceNode != null && !namespaceNode.IsNamespace) { namespaceNode = namespaceNode.Parent; } if (namespaceNode != null) { model.NamespaceName = namespaceNode.GetNamespaceName(); model.Namespace = GetNamespaceByName(model.NamespaceName); } } return model; }