/// <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; }
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(); }
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); } }
/// <summary> /// Add another DiagnosticBag to the bag and free the argument. /// </summary> public void AddRangeAndFree(DiagnosticBag bag) { AddRange(bag); bag.Free(); }