/// <summary> /// Creates a separated list of nodes from a sequence of nodes and a sequence of separator tokens. /// </summary> /// <typeparam name="TNode">The specific type of the element nodes.</typeparam> /// <param name="nodes">A sequence of syntax nodes.</param> /// <param name="separators">A sequence of token to be interleaved between the nodes. The number of tokens must /// be one less than the number of nodes.</param> public virtual SeparatedSyntaxList <TNode> SeparatedList <TNode>(IEnumerable <TNode> nodes, IEnumerable <SyntaxToken> separators) where TNode : SyntaxNode { // Interleave the nodes and the separators. The number of separators must be equal to or 1 less than the number of nodes or // an argument exception is thrown. if (nodes != null) { IEnumerator <TNode> enumerator = nodes.GetEnumerator(); SeparatedSyntaxListBuilder <TNode> builder = SeparatedSyntaxListBuilder <TNode> .Create(); if (separators != null) { foreach (SyntaxToken token in separators) { if (!enumerator.MoveNext()) { throw new ArgumentException($"{nameof(nodes)} must not be empty.", nameof(nodes)); } builder.Add(enumerator.Current); builder.AddSeparator(token); } } if (enumerator.MoveNext()) { builder.Add(enumerator.Current); if (enumerator.MoveNext()) { throw new ArgumentException($"{nameof(separators)} must have 1 fewer element than {nameof(nodes)}", nameof(separators)); } } return(builder.ToList()); } if (separators != null) { throw new ArgumentException($"When {nameof(nodes)} is null, {nameof(separators)} must also be null.", nameof(separators)); } return(default(SeparatedSyntaxList <TNode>)); }
/// <summary> /// Creates a separated list of nodes from a sequence of nodes, synthesizing comma separators in between. /// </summary> /// <typeparam name="TNode">The specific type of the element nodes.</typeparam> /// <param name="nodes">A sequence of syntax nodes.</param> public virtual SeparatedSyntaxList <TNode> SeparatedList <TNode>(IEnumerable <TNode> nodes, SyntaxKind separatorKind) where TNode : SyntaxNode { if (nodes == null) { return(default(SeparatedSyntaxList <TNode>)); } var collection = nodes as ICollection <TNode>; if (collection != null && collection.Count == 0) { return(default(SeparatedSyntaxList <TNode>)); } using (var enumerator = nodes.GetEnumerator()) { if (!enumerator.MoveNext()) { return(default(SeparatedSyntaxList <TNode>)); } var firstNode = enumerator.Current; if (!enumerator.MoveNext()) { return(SingletonSeparatedList <TNode>(firstNode)); } var builder = new SeparatedSyntaxListBuilder <TNode>(collection != null ? collection.Count : 3); builder.Add(firstNode); var commaToken = Token(separatorKind); do { builder.AddSeparator(commaToken); builder.Add(enumerator.Current); }while (enumerator.MoveNext()); return(builder.ToList()); } }
private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive) { pragma = CheckFeatureAvailability(pragma, MessageID.IDS_FeaturePragma); bool hasError = false; if (this.CurrentToken.ContextualKind == SyntaxKind.WarningKeyword) { var warning = this.EatContextualToken(SyntaxKind.WarningKeyword); SyntaxToken style; if (this.CurrentToken.Kind == SyntaxKind.DisableKeyword || this.CurrentToken.Kind == SyntaxKind.RestoreKeyword) { style = this.EatToken(); var ids = new SeparatedSyntaxListBuilder<ExpressionSyntax>(10); while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken) { SyntaxToken id; ExpressionSyntax idExpression; if (this.CurrentToken.Kind == SyntaxKind.NumericLiteralToken) { // Previous versions of the compiler used to report a warning (CS1691) // whenever an unrecognized warning code was supplied in a #pragma directive // (or via /nowarn /warnaserror flags on the command line). // Going forward, we won't generate any warning in such cases. This will make // maintainance of backwards compatibility easier (we no longer need to worry // about breaking existing projects / command lines if we deprecate / remove // an old warning code). id = this.EatToken(); idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id); } else if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken) { // Lexing / parsing of identifiers inside #pragma warning directives is identical // to that inside #define directives except that very long identifiers inside #define // are truncated to 128 characters to maintain backwards compatibility with previous // versions of the compiler. (See TruncateIdentifier() below.) // Since support for identifiers inside #pragma warning directivess is new, // we don't have any backwards compatibility constraints. So we can preserve the // identifier exactly as it appears in source. id = this.EatToken(); idExpression = SyntaxFactory.IdentifierName(id); } else { id = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_IdentifierOrNumericLiteralExpected, reportError: isActive); idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id); } hasError = hasError || id.ContainsDiagnostics; ids.Add(idExpression); if (this.CurrentToken.Kind != SyntaxKind.CommaToken) { break; } ids.AddSeparator(this.EatToken()); } var end = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true); return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, ids.ToList(), end, isActive); } else { style = this.EatToken(SyntaxKind.DisableKeyword, ErrorCode.WRN_IllegalPPWarning, reportError: isActive); var end = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true); return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), end, isActive); } } else if (this.CurrentToken.Kind == SyntaxKind.ChecksumKeyword) { var checksum = this.EatToken(); var file = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive); var guid = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !file.IsMissing); if (isActive && !guid.IsMissing) { Guid tmp; if (!Guid.TryParse(guid.ValueText, out tmp)) { guid = this.AddError(guid, ErrorCode.WRN_IllegalPPChecksum); } } var bytes = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !guid.IsMissing); if (isActive && !bytes.IsMissing) { if (bytes.ValueText.Length % 2 != 0) { bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum); } else { foreach (char c in bytes.ValueText) { if (!SyntaxFacts.IsHexDigit(c)) { bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum); break; } } } } hasError = file.ContainsDiagnostics | guid.ContainsDiagnostics | bytes.ContainsDiagnostics; var eod = this.ParseEndOfDirective(ignoreErrors: hasError, afterPragma: true); return SyntaxFactory.PragmaChecksumDirectiveTrivia(hash, pragma, checksum, file, guid, bytes, eod, isActive); } else { var warning = this.EatToken(SyntaxKind.WarningKeyword, ErrorCode.WRN_IllegalPragma, reportError: isActive); var style = this.EatToken(SyntaxKind.DisableKeyword, reportError: false); var eod = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true); return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), eod, isActive); } }
private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive) { pragma = CheckFeatureAvailability(pragma, MessageID.IDS_FeaturePragma); bool hasError = false; if (this.CurrentToken.ContextualKind == SyntaxKind.WarningKeyword) { var warning = this.EatContextualToken(SyntaxKind.WarningKeyword); SyntaxToken style; if (this.CurrentToken.Kind == SyntaxKind.DisableKeyword || this.CurrentToken.Kind == SyntaxKind.RestoreKeyword) { style = this.EatToken(); var ids = new SeparatedSyntaxListBuilder<ExpressionSyntax>(10); while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken) { SyntaxToken id; ExpressionSyntax idExpression; if (this.CurrentToken.Kind == SyntaxKind.NumericLiteralToken || this.CurrentToken.Kind == SyntaxKind.StringLiteralToken) { id = this.EatToken(); if (isActive) { if (id.Kind == SyntaxKind.NumericLiteralToken) { int compilerWarningNumber = (int)id.Value; if (ErrorFacts.GetSeverity((ErrorCode)compilerWarningNumber) != DiagnosticSeverity.Warning) { id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, compilerWarningNumber); } } else { string value = (string)id.Value; var messageProvider = MessageProvider.Instance; if (string.IsNullOrWhiteSpace(value)) { id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, value); } else if (value.StartsWith(messageProvider.CodePrefix)) { // For diagnostic IDs of the form "CS[0-9]*", verify the error code is that of a warning int compilerWarningNumber; if (int.TryParse(value.Substring(messageProvider.CodePrefix.Length), NumberStyles.None, CultureInfo.InvariantCulture, out compilerWarningNumber) && (messageProvider.GetIdForErrorCode(compilerWarningNumber) != value || ErrorFacts.GetSeverity((ErrorCode)compilerWarningNumber) != DiagnosticSeverity.Warning)) { id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, value); } } } } var expressionKind = id.Kind == SyntaxKind.NumericLiteralToken ? SyntaxKind.NumericLiteralExpression : SyntaxKind.StringLiteralExpression; idExpression = SyntaxFactory.LiteralExpression(expressionKind, id); } else { id = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_StringOrNumericLiteralExpected, reportError: isActive); idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id); } hasError = hasError || id.ContainsDiagnostics; ids.Add(idExpression); if (this.CurrentToken.Kind != SyntaxKind.CommaToken) { break; } ids.AddSeparator(this.EatToken()); } var end = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true); return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, ids.ToList(), end, isActive); } else { style = this.EatToken(SyntaxKind.DisableKeyword, ErrorCode.WRN_IllegalPPWarning, reportError: isActive); var end = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true); return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), end, isActive); } } else if (this.CurrentToken.Kind == SyntaxKind.ChecksumKeyword) { var checksum = this.EatToken(); var file = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive); var guid = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !file.IsMissing); if (isActive && !guid.IsMissing) { Guid tmp; if (!Guid.TryParse(guid.ValueText, out tmp)) { guid = this.AddError(guid, ErrorCode.WRN_IllegalPPChecksum); } } var bytes = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !guid.IsMissing); if (isActive && !bytes.IsMissing) { if (bytes.ValueText.Length % 2 != 0) { bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum); } else { foreach (char c in bytes.ValueText) { if (!SyntaxFacts.IsHexDigit(c)) { bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum); break; } } } } hasError = file.ContainsDiagnostics | guid.ContainsDiagnostics | bytes.ContainsDiagnostics; var eod = this.ParseEndOfDirective(ignoreErrors: hasError, afterPragma: true); return SyntaxFactory.PragmaChecksumDirectiveTrivia(hash, pragma, checksum, file, guid, bytes, eod, isActive); } else { var warning = this.EatToken(SyntaxKind.WarningKeyword, ErrorCode.WRN_IllegalPragma, reportError: isActive); var style = this.EatToken(SyntaxKind.DisableKeyword, reportError: false); var eod = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true); return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), eod, isActive); } }