string GetDocumentation(XmlDocumentationProvider docProvider, IMemberRef mr) { var sb = new StringBuilder(); var doc = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(mr, sb)); if (doc != null) return doc; var method = mr as IMethod; if (method == null) return null; string name = method.Name; if (name.StartsWith("set_") || name.StartsWith("get_")) { var md = Resolve(method) as MethodDef; if (md == null) return null; mr = md.DeclaringType.Properties.FirstOrDefault(p => p.GetMethod == md || p.SetMethod == md); return docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(mr, sb)); } else if (name.StartsWith("add_")) { var md = Resolve(method) as MethodDef; if (md == null) return null; mr = md.DeclaringType.Events.FirstOrDefault(p => p.AddMethod == md); return docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(mr, sb)); } else if (name.StartsWith("remove_")) { var md = Resolve(method) as MethodDef; if (md == null) return null; mr = md.DeclaringType.Events.FirstOrDefault(p => p.RemoveMethod == md); return docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(mr, sb)); } return null; }
public void GetSummary_ReturnsExpectedSummarys(string id, string expectedSummary) { // Arrange var xmlDocumentationProvider = new XmlDocumentationProvider(XmlTestFileLocation); // Act var summary = xmlDocumentationProvider.GetSummary(id); // Assert Assert.Equal(expectedSummary, summary, StringComparer.Ordinal); }
public override string GetDescription(int index) { string description = string.Empty; NVIdNode idNode = _declarations[index].IdNode; if (idNode is NVClassNode) { NVClassNode classNode = (NVClassNode)idNode; XmlDocumentationProvider documentationProvider = new XmlDocumentationProvider(classNode.AssemblyFileName); string classSummary = documentationProvider.GetTypeDocumentation(classNode.FullName); if (!string.IsNullOrEmpty(classSummary)) { description = string.Format("class {0}\n{1}", classNode.FullName, classSummary); } else { description = string.Format("class {0}", classNode.FullName); } } else if (idNode is NVLocalNode) { NVClassNode classNode = (NVClassNode)idNode.Type; if (classNode != null) { XmlDocumentationProvider documentationProvider = new XmlDocumentationProvider(classNode.AssemblyFileName); description = documentationProvider.GetTypeDocumentation(classNode.FullName); } } else if (idNode is NVMethodNode) { NVClassNode classNode = (NVClassNode)((NVMethodNode)idNode).Parent; if (classNode != null) { XmlDocumentationProvider documentationProvider = new XmlDocumentationProvider(classNode.AssemblyFileName); description = documentationProvider.GetMethodDocumentation(classNode.FullName, idNode.Name); } } // Return the documentation or an error message if (!string.IsNullOrEmpty(description)) { return description; } return string.Format("Could not retrieve documentation for AST node '{0}' (because it is not supported).", idNode != null ? idNode.GetType().Name : ""); }
public void GetRemarks_ReturnsExpectedRemarks(string id, string expectedRemarks) { // Arrange var xmlDocumentationProvider = new XmlDocumentationProvider(XmlTestFileLocation); // Act var remarks = xmlDocumentationProvider.GetRemarks(id); // Assert Assert.Equal(expectedRemarks, remarks, StringComparer.Ordinal); }
private static DocumentationProvider GetDocumentationProvider(string assemblyFilePath, string assemblyName) { var result = DocumentationProvider.Default; string xmlFile; if (AssemblyNameToXmlDocFileMap.TryGetValue(assemblyName, out xmlFile)) { result = new XmlDocumentationProvider(xmlFile); } return result; }
private XmlDocumentationProvider GetXmlDocProvider(Assembly assembly) { var xmlPath = FindXmlDocPath(assembly); System.Diagnostics.Debug.Print("GetXmlDocProvider {0}", xmlPath); if (xmlPath == null || File.Exists(xmlPath) == false) { System.Diagnostics.Debug.Print("GetXmlDocProvider not found"); return null; } var key = xmlPath.ToLower(); XmlDocumentationProvider provider; if (_providers.TryGetValue(key, out provider) == false) { provider = new XmlDocumentationProvider(xmlPath); _providers[key] = provider; } return provider; }
public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context) { List <ISymbol> symbols = new List <ISymbol>(); // Create the compilation (have to supply an XmlReferenceResolver to handle include XML doc comments) MetadataReference mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); Compilation compilation = CSharpCompilation .Create(CompilationAssemblyName) .WithReferences(mscorlib) .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, xmlReferenceResolver: new XmlFileResolver(context.FileSystem.RootPath.FullPath))); // Handle input documents if (_inputDocuments) { // Get syntax trees (supply path so that XML doc includes can be resolved) ConcurrentBag <SyntaxTree> syntaxTrees = new ConcurrentBag <SyntaxTree>(); Parallel.ForEach(inputs, input => { using (Stream stream = input.GetStream()) { SourceText sourceText = SourceText.From(stream); syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText, path: input.String(Keys.SourceFilePath, string.Empty))); } }); compilation = compilation.AddSyntaxTrees(syntaxTrees); } // Handle assemblies IEnumerable <IFile> assemblyFiles = context.FileSystem.GetInputFiles(_assemblyGlobs) .Where(x => (x.Path.Extension == ".dll" || x.Path.Extension == ".exe") && x.Exists); MetadataReference[] assemblyReferences = assemblyFiles.Select(assemblyFile => { // Create the metadata reference for the compilation IFile xmlFile = context.FileSystem.GetFile(assemblyFile.Path.ChangeExtension("xml")); if (xmlFile.Exists) { Trace.Verbose($"Creating metadata reference for assembly {assemblyFile.Path.FullPath} with XML documentation file"); using (Stream xmlStream = xmlFile.OpenRead()) { using (MemoryStream xmlBytes = new MemoryStream()) { xmlStream.CopyTo(xmlBytes); return(MetadataReference.CreateFromStream(assemblyFile.OpenRead(), documentation: XmlDocumentationProvider.CreateFromBytes(xmlBytes.ToArray()))); } } } Trace.Verbose($"Creating metadata reference for assembly {assemblyFile.Path.FullPath} without XML documentation file"); return((MetadataReference)MetadataReference.CreateFromStream(assemblyFile.OpenRead())); }).ToArray(); if (assemblyReferences.Length > 0) { compilation = compilation.AddReferences(assemblyReferences); symbols.AddRange(assemblyReferences .Select(x => (IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(x)) .Select(x => _assemblySymbols ? x : (ISymbol)x.GlobalNamespace)); } // Get and return the document tree symbols.Add(compilation.Assembly.GlobalNamespace); AnalyzeSymbolVisitor visitor = new AnalyzeSymbolVisitor(compilation, context, _symbolPredicate, _writePath ?? (x => DefaultWritePath(x, _writePathPrefix)), _cssClasses, _docsForImplicitSymbols, _assemblySymbols); foreach (ISymbol symbol in symbols) { visitor.Visit(symbol); } return(visitor.Finish()); }
public DocumentationProvider GetDocumentationProvider(string assemblyPath) { if (assemblyPath == null) { throw new ArgumentNullException(nameof(assemblyPath)); } assemblyPath = Path.ChangeExtension(assemblyPath, "xml"); if (!_assemblyPathToDocumentationProviderMap.TryGetValue(assemblyPath, out var provider)) { provider = _assemblyPathToDocumentationProviderMap.GetOrAdd(assemblyPath, _path => XmlDocumentationProvider.CreateFromFile(_path)); } return(provider); }
/// <summary> /// Creates documentation provider for assembly <i>asmPath</i>. /// Returns null if its xml file does not exist. /// Returns _DocumentationProvider if xml file is big and found or successfully created and successfully loaded database for it. /// Else returns XmlDocumentationProvider. /// </summary> public static DocumentationProvider Create(string asmPath) { if (s_d.TryGetValue(asmPath, out var dp)) { return(dp); } var xmlPath = Path.ChangeExtension(asmPath, "xml"); if (!AFile.GetProperties(xmlPath, out var px)) { return(null); } if (px.Size >= 10_000) { var md5 = new Au.Util.AHash.MD5(); md5.Add(xmlPath.Lower()); var dbPath = AFolders.ThisAppTemp + md5.Hash.ToString() + ".db"; try { if (!AFile.GetProperties(dbPath, out var pd) || pd.LastWriteTimeUtc != px.LastWriteTimeUtc) { //ADebug.Print($"creating db: {asmPath} -> {dbPath}"); AFile.Delete(dbPath); using (var d = new ASqlite(dbPath)) { using var trans = d.Transaction(); d.Execute("CREATE TABLE doc (name TEXT PRIMARY KEY, xml TEXT)"); using var statInsert = d.Statement("INSERT INTO doc VALUES (?, ?)"); var xr = AExtXml.LoadElem(xmlPath); foreach (var e in xr.Descendants("member")) { var name = e.Attr("name"); //remove <remarks> and <example>. foreach (var v in e.Descendants("remarks").ToArray()) { v.Remove(); } foreach (var v in e.Descendants("example").ToArray()) { v.Remove(); } using var reader = e.CreateReader(); reader.MoveToContent(); var xml = reader.ReadInnerXml(); //AOutput.Write(name, xml); statInsert.BindAll(name, xml).Step(); statInsert.Reset(); } trans.Commit(); d.Execute("VACUUM"); } File.SetLastWriteTimeUtc(dbPath, px.LastWriteTimeUtc); } var db = new ASqlite(dbPath, SLFlags.SQLITE_OPEN_READONLY); //never mind: we don't dispose it on process exit s_d[asmPath] = dp = new _DocumentationProvider { _db = db }; return(dp); } catch (Exception ex) { ADebug.Print(ex.ToStringWithoutStack()); } } return(XmlDocumentationProvider.CreateFromFile(xmlPath)); }
public DocumentationProvider GetDocumentationProvider(string assemblyPath) { if (assemblyPath == null) { throw new ArgumentNullException("assemblyPath"); } assemblyPath = Path.ChangeExtension(assemblyPath, "xml"); DocumentationProvider provider; if (!this.assemblyPathToDocumentationProviderMap.TryGetValue(assemblyPath, out provider)) { provider = this.assemblyPathToDocumentationProviderMap.GetOrAdd(assemblyPath, _path => XmlDocumentationProvider.Create(_path)); } return(provider); }
void TextViewMouseHover(object sender, MouseEventArgs e) { TextViewPosition?position = textEditor.TextArea.TextView.GetPosition(e.GetPosition(textEditor.TextArea.TextView) + textEditor.TextArea.TextView.ScrollOffset); if (position == null) { return; } int offset = textEditor.Document.GetOffset(position.Value.Location); if (referenceElementGenerator.References == null) { return; } ReferenceSegment seg = referenceElementGenerator.References.FindSegmentsContaining(offset).FirstOrDefault(); if (seg == null) { return; } object content = GenerateTooltip(seg); if (tooltip != null) { tooltip.IsOpen = false; } if (content != null) { tooltip = new ToolTip() { Content = content, IsOpen = true } } ; } object GenerateTooltip(ReferenceSegment segment) { if (segment.Reference is Mono.Cecil.Cil.OpCode) { Mono.Cecil.Cil.OpCode code = (Mono.Cecil.Cil.OpCode)segment.Reference; string encodedName = code.Code.ToString(); string opCodeHex = code.Size > 1 ? string.Format("0x{0:x2}{1:x2}", code.Op1, code.Op2) : string.Format("0x{0:x2}", code.Op2); XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation; if (docProvider != null) { string documentation = docProvider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + encodedName); if (documentation != null) { XmlDocRenderer renderer = new XmlDocRenderer(); renderer.AppendText(string.Format("{0} ({1}) - ", code.Name, opCodeHex)); renderer.AddXmlDocumentation(documentation); return(renderer.CreateTextBlock()); } } return(string.Format("{0} ({1})", code.Name, opCodeHex)); } else if (segment.Reference is MemberReference) { MemberReference mr = (MemberReference)segment.Reference; // if possible, resolve the reference if (mr is TypeReference) { mr = ((TypeReference)mr).Resolve() ?? mr; } else if (mr is MethodReference) { mr = ((MethodReference)mr).Resolve() ?? mr; } XmlDocRenderer renderer = new XmlDocRenderer(); renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(mr)); try { XmlDocumentationProvider docProvider = XmlDocLoader.LoadDocumentation(mr.Module); if (docProvider != null) { string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(mr)); if (documentation != null) { renderer.AppendText(Environment.NewLine); renderer.AddXmlDocumentation(documentation); } } } catch (XmlException) { // ignore } return(renderer.CreateTextBlock()); } return(null); }
void TextViewMouseHover(object sender, MouseEventArgs e) { TextViewPosition?position = GetPositionFromMousePosition(); if (position == null) { return; } int offset = textEditor.Document.GetOffset(position.Value.Location); if (referenceElementGenerator.References == null) { return; } ReferenceSegment seg = referenceElementGenerator.References.FindSegmentsContaining(offset).FirstOrDefault(); if (seg == null) { return; } object content = GenerateTooltip(seg); if (tooltip != null) { tooltip.IsOpen = false; } if (content != null) { tooltip = new ToolTip() { Content = content, IsOpen = true } } ; } object GenerateTooltip(ReferenceSegment segment) { if (segment.Reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo code) { XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation; if (docProvider != null) { string documentation = docProvider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + code.EncodedName); if (documentation != null) { XmlDocRenderer renderer = new XmlDocRenderer(); renderer.AppendText($"{code.Name} (0x{code.Code:x}) - "); renderer.AddXmlDocumentation(documentation); return(renderer.CreateTextBlock()); } } return($"{code.Name} (0x{code.Code:x})"); } else if (segment.Reference is IEntity entity) { return(CreateTextBlockForEntity(entity)); } else if (segment.Reference is ValueTuple <PEFile, System.Reflection.Metadata.EntityHandle> unresolvedEntity) { var typeSystem = new DecompilerTypeSystem(unresolvedEntity.Item1, unresolvedEntity.Item1.GetAssemblyResolver(), TypeSystemOptions.Default | TypeSystemOptions.Uncached); try { IEntity resolved = typeSystem.MainModule.ResolveEntity(unresolvedEntity.Item2); if (resolved == null) { return(null); } return(CreateTextBlockForEntity(resolved)); } catch (BadImageFormatException) { return(null); } } return(null); }
private static async Task <ProjectHandler> TryGetPhpProjectAsync(string projectFile, ILogTarget log) { try { Project project = LoadProject(projectFile); if (!IsPhpProject(project)) { return(null); } SetupMultitargetingIfNecessary(project); var buildResult = await ResolveReferencesAsync(project); var projectInstance = buildResult.ProjectStateAfterBuild; var metadataReferences = GatherReferences(project, projectInstance, buildResult) .Select(path => MetadataReference.CreateFromFile(path, documentation: XmlDocumentationProvider.CreateFromFile(Path.ChangeExtension(path, "xml")))) .ToArray(); if (metadataReferences.Length == 0) { // dotnet restore hasn't run yet log?.LogMessage($"{Path.GetFileName(projectFile)}: could not be built; "); return(null); } var options = new PhpCompilationOptions( outputKind: OutputKind.DynamicallyLinkedLibrary, baseDirectory: Path.GetDirectoryName(projectFile), // compilation expects platform-specific slashes (backslashes on windows) specificDiagnosticOptions: null, sdkDirectory: null); // TODO: Get from MSBuild string projectName = Path.GetFileNameWithoutExtension(projectFile); var encoding = TryParseEncodingName(projectInstance.GetPropertyValue("CodePage")) ?? Encoding.UTF8; var nowarn = projectInstance.GetPropertyValue("NoWarn"); if (nowarn != null) { options = options.WithSpecificDiagnosticOptions(ParseNoWarn(nowarn)); } var syntaxTrees = ParseSourceFiles(projectInstance, encoding); var compilation = PhpCompilation.Create( projectName, syntaxTrees, references: metadataReferences, options: options); return(new ProjectHandler(compilation, projectInstance, encoding)); } catch (Exception ex) { log?.LogMessage($"{Path.GetFileName(projectFile)}: {ex.Message}"); return(null); } }
static string LookupLocalizedXmlDoc(string fileName) { return(XmlDocumentationProvider.LookupLocalizedXmlDoc(fileName)); }
/// <summary> /// Gets standard framework dependencies and resolves any package dependencies passed in as /// MetadataReferences to provide the actual assembly file and documentation file together. /// </summary> /// <param name="dependencies">Package dependencies to be located on the file system.</param> /// <returns>An array of <see cref="MetadataReference"/> containing all resolved assemblies and documentation.</returns> public MetadataReference[] ResolveReferences(Dependency[] dependencies) { // Ensure we never have a null reference for the dependency list. if (dependencies == null) { throw new ArgumentNullException(nameof(dependencies)); } var assemblies = new[] { typeof(Uri).Assembly, typeof(object).Assembly, typeof(Enumerable).Assembly, typeof(ConfigurationManager).Assembly, typeof(JObject).Assembly, typeof(HttpClient).Assembly, typeof(HttpContentExtensions).Assembly, typeof(Common.RouteRequest).Assembly, typeof(XmlElement).Assembly, typeof(XObject).Assembly, typeof(DataContractAttribute).Assembly, typeof(BasicHttpBinding).Assembly, typeof(DataSet).Assembly, typeof(DataRowExtensions).Assembly, typeof(Geography).Assembly, typeof(Size).Assembly }; // Pull in cache containing a list of documentation files to make finding an assemblies associated // XML doc file to be added to the MetadataReference. This directory search is only done once on // first request. var fileLookup = GetDocumentationLookup(); return(assemblies .Select(a => { // Locate the name of the assembly to determine what the documentation file name is. var assemblyName = a.GetName().Name; // Attempt to locate an xml documentation file in the cache. if (fileLookup.TryGetValue(assemblyName, out string docPath)) { return MetadataReference.CreateFromFile(a.Location, documentation: XmlDocumentationProvider.CreateFromFile(docPath)); } // Otherwise we have no documentation file and we'll return it without a doc provider. return MetadataReference.CreateFromFile(a.Location); }) // Iterate through each dependency to get actual MetadataReferences containing the assembly paths // and documentation paths for the assemblies contained with the package folders. // There can be multiple assemblies required for each NuGet package, so the ResolvePackageReferencesAsync() // method returns an array of MetadataReferences for each of the assemblies and matching documentation files. // Add the references to the final output to be included in the compilation. .Concat(dependencies.SelectMany(d => ResolvePackageReferences(d))) .ToArray()); }
void TextViewMouseHover(object sender, MouseEventArgs e) { TextViewPosition?position = textEditor.TextArea.TextView.GetPosition(e.GetPosition(textEditor.TextArea.TextView) + textEditor.TextArea.TextView.ScrollOffset); if (position == null) { return; } int offset = textEditor.Document.GetOffset(position.Value); ReferenceSegment seg = referenceElementGenerator.References.FindSegmentsContaining(offset).FirstOrDefault(); if (seg == null) { return; } object content = GenerateTooltip(seg); if (tooltip != null) { tooltip.IsOpen = false; } if (content != null) { tooltip = new ToolTip() { Content = content, IsOpen = true } } ; } object GenerateTooltip(ReferenceSegment segment) { if (segment.Reference is Mono.Cecil.Cil.OpCode) { Mono.Cecil.Cil.OpCode code = (Mono.Cecil.Cil.OpCode)segment.Reference; string encodedName = code.Code.ToString(); string opCodeHex = code.Size > 1 ? string.Format("0x{0:x2}{1:x2}", code.Op1, code.Op2) : string.Format("0x{0:x2}", code.Op2); string documentationFile = FindDocumentation("mscorlib.xml"); string text = ""; if (documentationFile != null) { XmlDocumentationProvider provider = new XmlDocumentationProvider(documentationFile); string documentation = provider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + encodedName); if (documentation != null) { text = StripXml(documentation); } } return(string.Format("{0} ({1}): {2}", code.Name, opCodeHex, text)); } return(null); } string StripXml(string xmlText) { try { using (XmlTextReader xml = new XmlTextReader(new StringReader(xmlText))) { StringBuilder ret = new StringBuilder(); while (xml.Read()) { if (xml.NodeType == XmlNodeType.Element) { string elname = xml.Name.ToLowerInvariant(); switch (elname) { case "summary": break; case "br": case "para": ret.AppendLine(); break; default: xml.Skip(); break; } } else if (xml.NodeType == XmlNodeType.Text) { ret.Append(Regex.Replace(xml.Value, @"\s+", " ")); } } return(ret.ToString()); } } catch (XmlException) { return(null); // invalid XML docu } } string FindDocumentation(string fileName) { string path = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); List <string> names = new List <string>(); EnumerateCultures(CultureInfo.CurrentCulture, names); names.Add("en"); names.Add("en-US"); names.Add("en-GB"); foreach (string name in names) { string location = Path.Combine(path, name, fileName); if (File.Exists(location)) { return(location); } } path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"); string loc = Path.Combine(path, fileName); if (File.Exists(loc)) { return(loc); } return(null); } void EnumerateCultures(CultureInfo info, List <string> names) { while (info != null) { names.Add(info.Name); info = info.Parent; if (info == info.Parent) { return; } } }