internal static ImmutableArray <Diagnostic> GetMethodBodyDiagnosticsForTree(CSharpCompilation compilation, SyntaxTree tree, TextSpan?span, CancellationToken cancellationToken) { DiagnosticBag diagnostics = DiagnosticBag.GetInstance(); CompileMethodBodies( compilation: compilation, moduleBeingBuilt: null, generateDebugInfo: false, hasDeclarationErrors: false, filter: null, filterTree: tree, filterSpanWithinTree: span, diagnostics: diagnostics, cancellationToken: cancellationToken); DocumentationCommentCompiler.WriteDocumentationCommentXml(compilation, null, null, diagnostics, cancellationToken, tree, span); // Report unused directives only if computing diagnostics for the entire tree. // Otherwise we cannot determine if a particular directive is used outside of the given sub-span within the tree. if (!span.HasValue || span.Value == tree.GetRoot(cancellationToken).FullSpan) { compilation.ReportUnusedImports(diagnostics, cancellationToken, tree); } return(diagnostics.ToReadOnlyAndFree()); }
internal static string GetAndCacheDocumentationComment(Symbol symbol, bool expandIncludes, ref string lazyXmlText) { // NOTE: For xml doc comments from source, the culture is ignored (we just return the // doc comment as it appears in source), so it won't affect what we cache. if (lazyXmlText == null) { string xmlText = DocumentationCommentCompiler.GetDocumentationCommentXml(symbol, expandIncludes, default(CancellationToken)); Interlocked.CompareExchange(ref lazyXmlText, xmlText, null); } return(lazyXmlText); }
internal static string GetDocumentationCommentText(CSharpCompilation compilation, string outputName = null, SyntaxTree filterTree = null, TextSpan?filterSpanWithinTree = null, bool ensureEnglishUICulture = false, params DiagnosticDescription[] expectedDiagnostics) { using (MemoryStream stream = new MemoryStream()) { DiagnosticBag diagnostics = DiagnosticBag.GetInstance(); CultureInfo saveUICulture = null; if (ensureEnglishUICulture) { var preferred = EnsureEnglishUICulture.PreferredOrNull; if (preferred == null) { ensureEnglishUICulture = false; } else { saveUICulture = CultureInfo.CurrentUICulture; CultureInfo.CurrentUICulture = preferred; } } try { DocumentationCommentCompiler.WriteDocumentationCommentXml(compilation, outputName, stream, diagnostics, default(CancellationToken), filterTree, filterSpanWithinTree); } finally { if (ensureEnglishUICulture) { CultureInfo.CurrentUICulture = saveUICulture; } } if (expectedDiagnostics != null) { diagnostics.Verify(expectedDiagnostics); } diagnostics.Free(); string text = Encoding.UTF8.GetString(stream.ToArray()); int length = text.IndexOf('\0'); if (length >= 0) { text = text.Substring(0, length); } return(text.Trim()); } }
private void BindName( XAttribute attribute, CSharpSyntaxNode originatingSyntax, bool isParameter, bool isTypeParameterRef ) { XmlNameAttributeSyntax attrSyntax = ParseNameAttribute( attribute.ToString(), attribute.Parent.Name.LocalName ); // CONSIDER: It would be easy to construct an XmlLocation from the XAttribute, so that // we could point the user at the actual problem. Location sourceLocation = originatingSyntax.Location; RecordSyntaxDiagnostics(attrSyntax, sourceLocation); // Respects DocumentationMode. MemberDeclarationSyntax memberDeclSyntax = BinderFactory.GetAssociatedMemberForXmlSyntax(originatingSyntax); Debug.Assert( memberDeclSyntax != null, "Why are we processing a documentation comment that is not attached to a member declaration?" ); var nameDiagnostics = BindingDiagnosticBag.GetInstance(_diagnostics); Binder binder = MakeNameBinder( isParameter, isTypeParameterRef, _memberSymbol, _compilation ); DocumentationCommentCompiler.BindName( attrSyntax, binder, _memberSymbol, ref _documentedParameters, ref _documentedTypeParameters, nameDiagnostics ); RecordBindingDiagnostics(nameDiagnostics, sourceLocation); // Respects DocumentationMode. nameDiagnostics.Free(); }
// Do the steps in compilation to get the method body diagnostics, but don't actually generate // IL or emit an assembly. public static ImmutableArray <Diagnostic> GetAllMethodBodyDiagnostics(CSharpCompilation compilation, CancellationToken cancellationToken) { DiagnosticBag diagnostics = DiagnosticBag.GetInstance(); CompileMethodBodies( compilation: compilation, moduleBeingBuilt: null, generateDebugInfo: false, hasDeclarationErrors: false, filter: null, filterTree: null, filterSpanWithinTree: null, diagnostics: diagnostics, cancellationToken: cancellationToken); DocumentationCommentCompiler.WriteDocumentationCommentXml(compilation, null, null, diagnostics, cancellationToken); compilation.ReportUnusedImports(diagnostics, cancellationToken); return(diagnostics.ToReadOnlyAndFree()); }
internal override bool GenerateResourcesAndDocumentationComments(CommonPEModuleBuilder moduleBuilder, Stream xmlDocStream, Stream win32Resources, string outputNameOverride, DiagnosticBag diagnostics, CancellationToken cancellationToken) { // Use a temporary bag so we don't have to refilter pre-existing diagnostics. DiagnosticBag methodBodyDiagnosticBag = DiagnosticBag.GetInstance(); var moduleBeingBuilt = (PEModuleBuilder)moduleBuilder; try { SetupWin32Resources(moduleBeingBuilt, win32Resources, methodBodyDiagnosticBag); ReportManifestResourceDuplicates( moduleBeingBuilt.ManifestResources, SourceAssembly.Modules.Skip(1).Select((m) => m.Name), //all modules except the first one AddedModulesResourceNames(methodBodyDiagnosticBag), methodBodyDiagnosticBag); if (!FilterAndAppendAndFreeDiagnostics(diagnostics, ref methodBodyDiagnosticBag)) { return(false); } } catch (Exception ex) { this.TrackException(ex); throw; } cancellationToken.ThrowIfCancellationRequested(); // Use a temporary bag so we don't have to refilter pre-existing diagnostics. DiagnosticBag xmlDiagnostics = DiagnosticBag.GetInstance(); string assemblyName = FileNameUtilities.ChangeExtension(moduleBeingBuilt.EmitOptions.OutputNameOverride, extension: null); DocumentationCommentCompiler.WriteDocumentationCommentXml(this, assemblyName, xmlDocStream, xmlDiagnostics, cancellationToken); if (!FilterAndAppendAndFreeDiagnostics(diagnostics, ref xmlDiagnostics)) { return(false); } return(true); }
internal static string GetDocumentationCommentText(CSharpCompilation compilation, string outputName = null, SyntaxTree filterTree = null, TextSpan?filterSpanWithinTree = null, params DiagnosticDescription[] expectedDiagnostics) { using (MemoryStream stream = new MemoryStream()) { DiagnosticBag diagnostics = DiagnosticBag.GetInstance(); DocumentationCommentCompiler.WriteDocumentationCommentXml(compilation, outputName, stream, diagnostics, default(CancellationToken), filterTree, filterSpanWithinTree); if (expectedDiagnostics != null) { diagnostics.Verify(expectedDiagnostics); } diagnostics.Free(); string text = Encoding.UTF8.GetString(stream.GetBuffer()); int length = text.IndexOf('\0'); if (length >= 0) { text = text.Substring(0, length); } return(text.Trim()); } }
internal static string GetDocumentationCommentText(CSharpCompilation compilation, string outputName = null, SyntaxTree filterTree = null, TextSpan?filterSpanWithinTree = null, bool ensureEnglishUICulture = false, params DiagnosticDescription[] expectedDiagnostics) { using (MemoryStream stream = new MemoryStream()) { DiagnosticBag diagnostics = DiagnosticBag.GetInstance(); var ensureObject = ensureEnglishUICulture ? new EnsureEnglishUICulture() : null; using (ensureObject) { DocumentationCommentCompiler.WriteDocumentationCommentXml(compilation, outputName, stream, diagnostics, default(CancellationToken), filterTree, filterSpanWithinTree); } if (expectedDiagnostics != null) { diagnostics.Verify(expectedDiagnostics); } diagnostics.Free(); byte[] buffer; ArraySegment <byte> bufferSegment; if (stream.TryGetBuffer(out bufferSegment) && bufferSegment.Count == bufferSegment.Array.Length) { buffer = bufferSegment.Array; } else { buffer = stream.ToArray(); } string text = Encoding.UTF8.GetString(buffer); int length = text.IndexOf('\0'); if (length >= 0) { text = text.Substring(0, length); } return(text.Trim()); } }
internal override bool CompileImpl(CommonPEModuleBuilder moduleBuilder, Stream win32Resources, Stream xmlDocStream, bool emittingPdb, DiagnosticBag diagnostics, Predicate <ISymbol> filterOpt, CancellationToken cancellationToken) { // The diagnostics should include syntax and declaration errors. We insert these before calling Emitter.Emit, so that the emitter // does not attempt to emit if there are declaration errors (but we do insert all errors from method body binding...) bool hasDeclarationErrors = false; // !FilterAndAppendDiagnostics(diagnostics, GetDiagnostics(CompilationStage.Declare, true, cancellationToken)); var moduleBeingBuilt = (PEModuleBuilder)moduleBuilder; if (moduleBeingBuilt.EmitOptions.EmitMetadataOnly) { throw new NotImplementedException(); } // Perform initial bind of method bodies in spite of earlier errors. This is the same // behavior as when calling GetDiagnostics() // Use a temporary bag so we don't have to refilter pre-existing diagnostics. DiagnosticBag methodBodyDiagnosticBag = DiagnosticBag.GetInstance(); SourceCompiler.CompileSources( this, moduleBeingBuilt, emittingPdb, hasDeclarationErrors, methodBodyDiagnosticBag, cancellationToken); SetupWin32Resources(moduleBeingBuilt, win32Resources, methodBodyDiagnosticBag); ReportManifestResourceDuplicates( moduleBeingBuilt.ManifestResources, SourceAssembly.Modules.Skip(1).Select((m) => m.Name), //all modules except the first one AddedModulesResourceNames(methodBodyDiagnosticBag), methodBodyDiagnosticBag); bool hasMethodBodyErrorOrWarningAsError = !FilterAndAppendAndFreeDiagnostics(diagnostics, ref methodBodyDiagnosticBag); if (hasDeclarationErrors || hasMethodBodyErrorOrWarningAsError) { return(false); } cancellationToken.ThrowIfCancellationRequested(); // Use a temporary bag so we don't have to refilter pre-existing diagnostics. DiagnosticBag xmlDiagnostics = DiagnosticBag.GetInstance(); string assemblyName = FileNameUtilities.ChangeExtension(moduleBeingBuilt.EmitOptions.OutputNameOverride, extension: null); DocumentationCommentCompiler.WriteDocumentationCommentXml(this, assemblyName, xmlDocStream, xmlDiagnostics, cancellationToken); if (!FilterAndAppendAndFreeDiagnostics(diagnostics, ref xmlDiagnostics)) { return(false); } //// Use a temporary bag so we don't have to refilter pre-existing diagnostics. //DiagnosticBag importDiagnostics = DiagnosticBag.GetInstance(); //this.ReportUnusedImports(importDiagnostics, cancellationToken); //if (!FilterAndAppendAndFreeDiagnostics(diagnostics, ref importDiagnostics)) //{ // Debug.Assert(false, "Should never produce an error"); // return false; //} return(true); }
public override void DefaultVisit(SyntaxNode node) { SyntaxKind nodeKind = node.CSharpKind(); bool diagnose = ((SyntaxTree)node.SyntaxTree).ReportDocumentationCommentDiagnostics(); if (nodeKind == SyntaxKind.XmlCrefAttribute) { XmlCrefAttributeSyntax crefAttr = (XmlCrefAttributeSyntax)node; CrefSyntax cref = crefAttr.Cref; BinderFactory factory = compilation.GetBinderFactory(cref.SyntaxTree); Binder binder = factory.GetBinder(cref); // Do this for the diagnostics, even if it won't be written. DiagnosticBag crefDiagnostics = DiagnosticBag.GetInstance(); string docCommentId = GetDocumentationCommentId(cref, binder, crefDiagnostics); if (diagnose) { diagnostics.AddRange(crefDiagnostics); } crefDiagnostics.Free(); if ((object)writer != null) { Visit(crefAttr.Name); VisitToken(crefAttr.EqualsToken); // Not going to visit normally, because we want to skip trivia within // the attribute value. crefAttr.StartQuoteToken.WriteTo(writer, leading: true, trailing: false); // We're not going to visit the cref because we want to bind it // and write a doc comment ID in its place. writer.Write(docCommentId); // Not going to visit normally, because we want to skip trivia within // the attribute value. crefAttr.EndQuoteToken.WriteTo(writer, leading: false, trailing: true); } // Don't descend - we've already written out everything necessary. return; } else if (nodeKind == SyntaxKind.XmlNameAttribute && diagnose) { XmlNameAttributeSyntax nameAttr = (XmlNameAttributeSyntax)node; BinderFactory factory = compilation.GetBinderFactory(nameAttr.SyntaxTree); Binder binder = factory.GetBinder(nameAttr, nameAttr.Identifier.SpanStart); // Do this for diagnostics, even if we aren't writing. DocumentationCommentCompiler.BindName(nameAttr, binder, memberSymbol, ref documentedParameters, ref documentedTypeParameters, diagnostics); // Do descend - we still need to write out the tokens of the attribute. } // NOTE: if we're recording any include element nodes (i.e. if includeElementsNodes is non-null), // then we want to record all of them, because we won't be able to distinguish in the XML DOM. if ((object)includeElementNodes != null) { XmlNameSyntax nameSyntax = null; if (nodeKind == SyntaxKind.XmlEmptyElement) { nameSyntax = ((XmlEmptyElementSyntax)node).Name; } else if (nodeKind == SyntaxKind.XmlElementStartTag) { nameSyntax = ((XmlElementStartTagSyntax)node).Name; } if ((object)nameSyntax != null && (object)nameSyntax.Prefix == null && DocumentationCommentXmlNames.ElementEquals(nameSyntax.LocalName.ValueText, DocumentationCommentXmlNames.IncludeElementName)) { includeElementNodes.Add((CSharpSyntaxNode)node); } } base.DefaultVisit(node); }