/// <summary>
 /// Filter out warnings based on the compiler options (/nowarn, /warn and /warnaserror) and the pragma warning directives.
 /// 'incoming' is freed.
 /// </summary>
 /// <returns>True when there is no error or warning treated as an error.</returns>
 internal override bool FilterAndAppendAndFreeDiagnostics(DiagnosticBag accumulator, ref DiagnosticBag incoming)
 {
     bool result = FilterAndAppendDiagnostics(accumulator, incoming.AsEnumerableWithoutResolution());
     incoming.Free();
     incoming = null;
     return result;
 }
Exemple #2
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);
            }
        protected sealed override void LazyAsyncMethodChecks(CancellationToken cancellationToken)
        {
            Debug.Assert(this.IsPartial == state.HasComplete(CompletionPart.FinishMethodChecks),
                         "Partial methods complete method checks during construction.  " +
                         "Other methods can't complete method checks before executing this method.");

            if (!this.IsAsync)
            {
                state.NotePartComplete(CompletionPart.StartAsyncMethodChecks);
                if (state.NotePartComplete(CompletionPart.FinishAsyncMethodChecks) && IsPartialDefinition)
                {
                    DeclaringCompilation.SymbolDeclaredEvent(this);
                }

                return;
            }

            DiagnosticBag diagnostics   = DiagnosticBag.GetInstance();
            Location      errorLocation = this.Locations[0];

            if (!this.IsGenericTaskReturningAsync(this.DeclaringCompilation) && !this.IsTaskReturningAsync(this.DeclaringCompilation) && !this.IsVoidReturningAsync())
            {
                // The return type of an async method must be void, Task or Task<T>
                diagnostics.Add(ErrorCode.ERR_BadAsyncReturn, errorLocation);
            }

            for (NamedTypeSymbol curr = this.ContainingType; (object)curr != null; curr = curr.ContainingType)
            {
                var sourceNamedTypeSymbol = curr as SourceNamedTypeSymbol;
                if ((object)sourceNamedTypeSymbol != null && sourceNamedTypeSymbol.HasSecurityCriticalAttributes)
                {
                    diagnostics.Add(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, errorLocation);
                    break;
                }
            }

            if ((this.ImplementationAttributes & System.Reflection.MethodImplAttributes.Synchronized) != 0)
            {
                diagnostics.Add(ErrorCode.ERR_SynchronizedAsyncMethod, errorLocation);
            }

            if (diagnostics.IsEmptyWithoutResolution)
            {
                ReportAsyncParameterErrors(this, diagnostics, errorLocation);
            }

            if (state.NotePartComplete(CompletionPart.StartAsyncMethodChecks))
            {
                AddSemanticDiagnostics(diagnostics);
                if (state.NotePartComplete(CompletionPart.FinishAsyncMethodChecks) && IsPartialDefinition)
                {
                    DeclaringCompilation.SymbolDeclaredEvent(this);
                }
            }
            else
            {
                state.SpinWaitComplete(CompletionPart.FinishAsyncMethodChecks, cancellationToken);
            }

            diagnostics.Free();
        }
Exemple #4
0
        private BoundPattern BindDeclarationPattern(
            DeclarationPatternSyntax node,
            TypeSymbol operandType,
            bool hasErrors,
            DiagnosticBag diagnostics)
        {
            Debug.Assert(operandType != (object)null);

            var typeSyntax = node.Type;

            bool        isVar;
            AliasSymbol aliasOpt;
            TypeSymbol  declType = BindType(typeSyntax, diagnostics, out isVar, out aliasOpt);

            if (isVar)
            {
                declType = operandType;
            }

            if (declType == (object)null)
            {
                Debug.Assert(hasErrors);
                declType = this.CreateErrorType("var");
            }

            var boundDeclType = new BoundTypeExpression(typeSyntax, aliasOpt, inferredType: isVar, type: declType);

            if (IsOperatorErrors(node, operandType, boundDeclType, diagnostics))
            {
                hasErrors = true;
            }
            else
            {
                hasErrors |= CheckValidPatternType(typeSyntax, operandType, declType,
                                                   isVar: isVar, patternTypeWasInSource: true, diagnostics: diagnostics);
            }

            switch (node.Designation.Kind())
            {
            case SyntaxKind.SingleVariableDesignation:
                break;

            case SyntaxKind.DiscardDesignation:
                return(new BoundDeclarationPattern(node, null, boundDeclType, isVar, hasErrors));

            default:
                throw ExceptionUtilities.UnexpectedValue(node.Designation.Kind());
            }

            var designation = (SingleVariableDesignationSyntax)node.Designation;
            var identifier  = designation.Identifier;
            SourceLocalSymbol localSymbol = this.LookupLocal(identifier);

            if (localSymbol != (object)null)
            {
                if ((InConstructorInitializer || InFieldInitializer) && ContainingMemberOrLambda.ContainingSymbol.Kind == SymbolKind.NamedType)
                {
                    Error(diagnostics, ErrorCode.ERR_ExpressionVariableInConstructorOrFieldInitializer, node);
                }

                localSymbol.SetType(declType);

                // Check for variable declaration errors.
                hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);

                if (!hasErrors)
                {
                    hasErrors = CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax);
                }

                return(new BoundDeclarationPattern(node, localSymbol, boundDeclType, isVar, hasErrors));
            }
            else
            {
                // We should have the right binder in the chain for a script or interactive, so we use the field for the pattern.
                Debug.Assert(node.SyntaxTree.Options.Kind != SourceCodeKind.Regular);
                GlobalExpressionVariable expressionVariableField = LookupDeclaredField(designation);
                DiagnosticBag            tempDiagnostics         = DiagnosticBag.GetInstance();
                expressionVariableField.SetType(declType, tempDiagnostics);
                tempDiagnostics.Free();
                BoundExpression receiver       = SynthesizeReceiver(node, expressionVariableField, diagnostics);
                var             variableAccess = new BoundFieldAccess(node, receiver, expressionVariableField, null, hasErrors);
                return(new BoundDeclarationPattern(node, expressionVariableField, variableAccess, boundDeclType, isVar, hasErrors));
            }
        }
        private bool Compile(
            string code,
            string path,
            DiagnosticBag diagnostics,
            Session session,
            Type delegateType,
            Type returnType,
            CancellationToken cancellationToken,
            bool isInteractive,
            bool isExecute,
            out CommonCompilation compilation,
            out Delegate factory)
        {
            Debug.Assert(delegateType != null);
            Debug.Assert(session != null);
            Debug.Assert(code != null);

            DiagnosticBag localDiagnostics = diagnostics ?? DiagnosticBag.GetInstance();
            IText         text             = new StringText(code);

            try
            {
                CommonCompilation localCompilation = CreateCompilation(text, path, isInteractive, session, returnType, localDiagnostics);
                if (localCompilation == null)
                {
                    Debug.Assert(localDiagnostics.HasAnyErrors());
                    CompilationError(localDiagnostics, diagnostics);
                    factory     = null;
                    compilation = null;
                    return(false);
                }

                // throw away all syntax warnings, they will be reported again by emit:
                localDiagnostics.Clear();

                // If we compile just in time for execution the user doesn't have access to the submission compilation just created.
                // If the previous submission hasn't been executed yet the execution would blow up when invoking the submission factory,
                // and after that the session would become unusable since there is no way how the user can re-execute the current submission.
                // So throw here before we save the submission into the session.
                if (isExecute)
                {
                    int slotIndex = localCompilation.GetSubmissionSlotIndex();
                    SessionHelpers.RequirePreviousSubmissionExecuted(session, slotIndex);
                }

                // TODO: (tomat)
                // Current CLR implementation of collectible assemblies doesn't support
                // references from uncollectible to collectible code.
                //
                // We can't emit collectible code if there is a possibility that we will
                // compile another submission in the session.
                //
                // A workaround might be to regenerate all collectible dependencies of an uncollectible
                // submission as uncollectible.
                //
                // For now we explicitly mark sessions as collectible in tests to keep test coverage.
                bool collectible = session.isCollectible;
                if (!TryEmitSubmission(localCompilation, localDiagnostics, delegateType, collectible, cancellationToken, out factory))
                {
                    Debug.Assert(localDiagnostics.HasAnyErrors());
                    CompilationError(localDiagnostics, diagnostics);
                    factory     = null;
                    compilation = null;
                    return(false);
                }

                session.SubmissionCompiled(localCompilation);

                compilation = localCompilation;
                return(true);
            }
            finally
            {
                if (localDiagnostics != diagnostics)
                {
                    localDiagnostics.Free();
                }
            }
        }
            /// <remarks>
            /// This method boils down to Rewrite(XDocument.Load(fileAttrValue).XPathSelectElements(pathAttrValue)).
            /// Everything else is error handling.
            /// </remarks>
            private XNode[] RewriteIncludeElement(XElement includeElement, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax, out string commentMessage)
            {
                Location location = GetIncludeElementLocation(includeElement, ref currentXmlFilePath, ref originatingSyntax);

                Debug.Assert(originatingSyntax != null);

                bool diagnose = originatingSyntax.SyntaxTree.ReportDocumentationCommentDiagnostics();

                if (!EnterIncludeElement(location))
                {
                    // NOTE: these must exist since we're already processed this node elsewhere in the call stack.
                    XAttribute fileAttr      = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.FileAttributeName));
                    XAttribute pathAttr      = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.PathAttributeName));
                    string     filePathValue = fileAttr.Value;
                    string     xpathValue    = pathAttr.Value;

                    if (diagnose)
                    {
                        _diagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new LocalizableErrorArgument(MessageID.IDS_OperationCausedStackOverflow));
                    }

                    commentMessage = ErrorFacts.GetMessage(MessageID.IDS_XMLNOINCLUDE, CultureInfo.CurrentUICulture);

                    // Don't inspect the children - we're already in a cycle.
                    return(new XNode[] { new XComment(commentMessage), includeElement.Copy(copyAttributeAnnotations: false) });
                }

                DiagnosticBag includeDiagnostics = DiagnosticBag.GetInstance();

                try
                {
                    XAttribute fileAttr = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.FileAttributeName));
                    XAttribute pathAttr = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.PathAttributeName));

                    bool hasFileAttribute = fileAttr != null;
                    bool hasPathAttribute = pathAttr != null;
                    if (!hasFileAttribute || !hasPathAttribute)
                    {
                        var subMessage = hasFileAttribute ? MessageID.IDS_XMLMISSINGINCLUDEPATH.Localize() : MessageID.IDS_XMLMISSINGINCLUDEFILE.Localize();
                        includeDiagnostics.Add(ErrorCode.WRN_InvalidInclude, location, subMessage);
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLBADINCLUDE);
                        return(null);
                    }

                    string xpathValue    = pathAttr.Value;
                    string filePathValue = fileAttr.Value;

                    var resolver = _compilation.Options.XmlReferenceResolver;
                    if (resolver == null)
                    {
                        includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new CodeAnalysisResourcesLocalizableErrorArgument(nameof(CodeAnalysisResources.XmlReferencesNotSupported)));
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                        return(null);
                    }

                    string resolvedFilePath = resolver.ResolveReference(filePathValue, currentXmlFilePath);

                    if (resolvedFilePath == null)
                    {
                        // NOTE: same behavior as IOException.
                        includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new CodeAnalysisResourcesLocalizableErrorArgument(nameof(CodeAnalysisResources.FileNotFound)));
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                        return(null);
                    }

                    if (_includedFileCache == null)
                    {
                        _includedFileCache = new DocumentationCommentIncludeCache(resolver);
                    }

                    try
                    {
                        XDocument doc;

                        try
                        {
                            doc = _includedFileCache.GetOrMakeDocument(resolvedFilePath);
                        }
                        catch (IOException e)
                        {
                            // NOTE: same behavior as resolvedFilePath == null.
                            includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, e.Message);
                            commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                            return(null);
                        }

                        Debug.Assert(doc != null);

                        string     errorMessage;
                        bool       invalidXPath;
                        XElement[] loadedElements = XmlUtilities.TrySelectElements(doc, xpathValue, out errorMessage, out invalidXPath);
                        if (loadedElements == null)
                        {
                            includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, errorMessage);

                            commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                            if (invalidXPath)
                            {
                                // leave the include node as is
                                return(null);
                            }

                            if (location.IsInSource)
                            {
                                // As in Dev11, return only the comment - drop the include element.
                                return(new XNode[] { new XComment(commentMessage) });
                            }
                            else
                            {
                                commentMessage = null;
                                return(Array.Empty <XNode>());
                            }
                        }

                        if (loadedElements != null && loadedElements.Length > 0)
                        {
                            // change the current XML file path for nodes contained in the document:
                            XNode[] result = RewriteMany(loadedElements, resolvedFilePath, originatingSyntax);

                            // The elements could be rewritten away if they are includes that refer to invalid
                            // (but existing and accessible) XML files.  If this occurs, behave as if we
                            // had failed to find any XPath results (as in Dev11).
                            if (result.Length > 0)
                            {
                                // NOTE: in this case, we do NOT visit the children of the include element -
                                // they are dropped.
                                commentMessage = null;
                                return(result);
                            }
                        }

                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLNOINCLUDE);
                        return(null);
                    }
                    catch (XmlException e)
                    {
                        // NOTE: invalid XML is handled differently from other errors - we don't include the include element
                        // in the results and the location is in the included (vs includING) file.

                        Location errorLocation = XmlLocation.Create(e, resolvedFilePath);
                        includeDiagnostics.Add(ErrorCode.WRN_XMLParseIncludeError, errorLocation, GetDescription(e)); //NOTE: location is in included file.

                        if (location.IsInSource)
                        {
                            commentMessage = string.Format(ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED2, CultureInfo.CurrentUICulture), resolvedFilePath);

                            // As in Dev11, return only the comment - drop the include element.
                            return(new XNode[] { new XComment(commentMessage) });
                        }
                        else
                        {
                            commentMessage = null;
                            return(Array.Empty <XNode>());
                        }
                    }
                }
                finally
                {
                    if (diagnose)
                    {
                        _diagnostics.AddRange(includeDiagnostics);
                    }

                    includeDiagnostics.Free();

                    LeaveIncludeElement(location);
                }
            }
        internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var incompletePart = state.NextIncompletePart;
                switch (incompletePart)
                {
                case CompletionPart.Attributes:
                    GetAttributes();
                    break;

                case CompletionPart.StartValidatingReferencedAssemblies:
                {
                    DiagnosticBag diagnostics = null;

                    if (AnyReferencedAssembliesAreLinked)
                    {
                        diagnostics = DiagnosticBag.GetInstance();
                        ValidateLinkedAssemblies(diagnostics, cancellationToken);
                    }

                    if (state.NotePartComplete(CompletionPart.StartValidatingReferencedAssemblies))
                    {
                        if (diagnostics != null)
                        {
                            this.assemblySymbol.DeclaringCompilation.SemanticDiagnostics.AddRange(diagnostics);
                        }

                        state.NotePartComplete(CompletionPart.FinishValidatingReferencedAssemblies);
                    }

                    if (diagnostics != null)
                    {
                        diagnostics.Free();
                    }
                }
                break;

                case CompletionPart.FinishValidatingReferencedAssemblies:
                    // some other thread has started validating references (otherwise we would be in the case above) so
                    // we just wait for it to both finish and report the diagnostics.
                    Debug.Assert(state.HasComplete(CompletionPart.StartValidatingReferencedAssemblies));
                    state.SpinWaitComplete(CompletionPart.FinishValidatingReferencedAssemblies, cancellationToken);
                    break;

                case CompletionPart.MembersCompleted:
                    this.GlobalNamespace.ForceComplete(locationOpt, cancellationToken);

                    if (this.GlobalNamespace.HasComplete(CompletionPart.MembersCompleted))
                    {
                        state.NotePartComplete(CompletionPart.MembersCompleted);
                    }
                    else
                    {
                        Debug.Assert(locationOpt != null, "If no location was specified, then the namespace members should be completed");
                        return;
                    }

                    break;

                case CompletionPart.None:
                    return;

                default:
                    // any other values are completion parts intended for other kinds of symbols
                    state.NotePartComplete(incompletePart);
                    break;
                }

                state.SpinWaitComplete(incompletePart, cancellationToken);
            }
        }
Exemple #8
0
 /// <summary>
 /// Add another DiagnosticBag to the bag and free the argument.
 /// </summary>
 public void AddRangeAndFree(DiagnosticBag bag)
 {
     AddRange(bag);
     bag.Free();
 }