Exemple #1
0
        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);
        }
Exemple #3
0
        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());
            }
        }
Exemple #4
0
            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();
            }
Exemple #5
0
        // 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());
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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());
            }
        }
Exemple #8
0
        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());
            }
        }
Exemple #9
0
        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);
        }
Exemple #10
0
            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);
            }