Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions eng/targets/Settings.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<!-- TODO: https://github.com/dotnet/roslyn/issues/71667 -->
<NoWarn>$(NoWarn);NU1507</NoWarn>

<NoWarn>$(NoWarn);RSEXPERIMENTAL005</NoWarn>

<CommonExtensionInstallationRoot>CommonExtensions</CommonExtensionInstallationRoot>
<LanguageServicesExtensionInstallationFolder>Microsoft\VBCSharp\LanguageServices</LanguageServicesExtensionInstallationFolder>

Expand Down
8 changes: 8 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpParseOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,14 @@ static void addSingleNamespaceParts(ArrayBuilder<ImmutableArray<string>> namespa
}
}

/// <summary>
/// Used for parsing .cs file-based programs.
/// </summary>
/// <remarks>
/// In this mode, ignored directives <c>#:</c> are allowed.
/// </remarks>
internal bool FileBasedProgram => Features.ContainsKey("FileBasedProgram");

internal override void ValidateOptions(ArrayBuilder<Diagnostic> builder)
{
ValidateOptions(builder, MessageProvider.Instance);
Expand Down
9 changes: 9 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -8122,4 +8122,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ExpressionTreeContainsExtensionPropertyAccess" xml:space="preserve">
<value>An expression tree may not contain an extension property access</value>
</data>
<data name="ERR_PPIgnoredFollowsToken" xml:space="preserve">
<value>'#:' directives cannot be after first token in file</value>
</data>
<data name="ERR_PPIgnoredNeedsFileBasedProgram" xml:space="preserve">
<value>'#:' directives can be only used in file-based programs ('/feature:FileBasedProgram')</value>
</data>
<data name="ERR_PPIgnoredFollowsIf" xml:space="preserve">
<value>'#:' directives cannot be after '#if' directive</value>
</data>
</root>
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2386,13 +2386,19 @@ internal enum ErrorCode
ERR_UnderspecifiedExtension = 9295,
ERR_ExpressionTreeContainsExtensionPropertyAccess = 9296,

ERR_PPIgnoredFollowsToken = 9297,
ERR_PPIgnoredNeedsFileBasedProgram = 9298,
ERR_PPIgnoredFollowsIf = 9299,

// Note: you will need to do the following after adding errors:
// 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
// 2) Add message to CSharpResources.resx

// Note: you will need to do the following after adding warnings:
// 1) Re-generate compiler code (eng\generate-compiler-code.cmd).
// 2) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
// 3) Update ErrorFacts.GetWarningLevel (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
// 4) Update DiagnosticTest.WarningLevel_2 (src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs)
// 5) Add message and '_Title' to CSharpResources.resx
}
}
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2503,6 +2503,9 @@ or ErrorCode.ERR_InvalidExtensionParameterReference
or ErrorCode.ERR_ValueParameterSameNameAsExtensionTypeParameter
or ErrorCode.ERR_UnderspecifiedExtension
or ErrorCode.ERR_ExpressionTreeContainsExtensionPropertyAccess
or ErrorCode.ERR_PPIgnoredFollowsToken
or ErrorCode.ERR_PPIgnoredNeedsFileBasedProgram
or ErrorCode.ERR_PPIgnoredFollowsIf
=> false,
};
#pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value.
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -26604,6 +26604,96 @@ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
=> new ShebangDirectiveTriviaSyntax(this.Kind, this.hashToken, this.exclamationToken, this.endOfDirectiveToken, this.isActive, GetDiagnostics(), annotations);
}

internal sealed partial class IgnoredDirectiveTriviaSyntax : DirectiveTriviaSyntax
{
internal readonly SyntaxToken hashToken;
internal readonly SyntaxToken colonToken;
internal readonly SyntaxToken endOfDirectiveToken;
internal readonly bool isActive;

internal IgnoredDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
: base(kind, diagnostics, annotations)
{
this.SlotCount = 3;
this.AdjustFlagsAndWidth(hashToken);
this.hashToken = hashToken;
this.AdjustFlagsAndWidth(colonToken);
this.colonToken = colonToken;
this.AdjustFlagsAndWidth(endOfDirectiveToken);
this.endOfDirectiveToken = endOfDirectiveToken;
this.isActive = isActive;
}

internal IgnoredDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive, SyntaxFactoryContext context)
: base(kind)
{
this.SetFactoryContext(context);
this.SlotCount = 3;
this.AdjustFlagsAndWidth(hashToken);
this.hashToken = hashToken;
this.AdjustFlagsAndWidth(colonToken);
this.colonToken = colonToken;
this.AdjustFlagsAndWidth(endOfDirectiveToken);
this.endOfDirectiveToken = endOfDirectiveToken;
this.isActive = isActive;
}

internal IgnoredDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
: base(kind)
{
this.SlotCount = 3;
this.AdjustFlagsAndWidth(hashToken);
this.hashToken = hashToken;
this.AdjustFlagsAndWidth(colonToken);
this.colonToken = colonToken;
this.AdjustFlagsAndWidth(endOfDirectiveToken);
this.endOfDirectiveToken = endOfDirectiveToken;
this.isActive = isActive;
}

public override SyntaxToken HashToken => this.hashToken;
public SyntaxToken ColonToken => this.colonToken;
public override SyntaxToken EndOfDirectiveToken => this.endOfDirectiveToken;
public override bool IsActive => this.isActive;

internal override GreenNode? GetSlot(int index)
=> index switch
{
0 => this.hashToken,
1 => this.colonToken,
2 => this.endOfDirectiveToken,
_ => null,
};

internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.IgnoredDirectiveTriviaSyntax(this, parent, position);

public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitIgnoredDirectiveTrivia(this);
public override TResult Accept<TResult>(CSharpSyntaxVisitor<TResult> visitor) => visitor.VisitIgnoredDirectiveTrivia(this);

public IgnoredDirectiveTriviaSyntax Update(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
if (hashToken != this.HashToken || colonToken != this.ColonToken || endOfDirectiveToken != this.EndOfDirectiveToken)
{
var newNode = SyntaxFactory.IgnoredDirectiveTrivia(hashToken, colonToken, endOfDirectiveToken, isActive);
var diags = GetDiagnostics();
if (diags?.Length > 0)
newNode = newNode.WithDiagnosticsGreen(diags);
var annotations = GetAnnotations();
if (annotations?.Length > 0)
newNode = newNode.WithAnnotationsGreen(annotations);
return newNode;
}

return this;
}

internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics)
=> new IgnoredDirectiveTriviaSyntax(this.Kind, this.hashToken, this.colonToken, this.endOfDirectiveToken, this.isActive, diagnostics, GetAnnotations());

internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
=> new IgnoredDirectiveTriviaSyntax(this.Kind, this.hashToken, this.colonToken, this.endOfDirectiveToken, this.isActive, GetDiagnostics(), annotations);
}

internal sealed partial class NullableDirectiveTriviaSyntax : DirectiveTriviaSyntax
{
internal readonly SyntaxToken hashToken;
Expand Down Expand Up @@ -26967,6 +27057,7 @@ internal partial class CSharpSyntaxVisitor<TResult>
public virtual TResult VisitReferenceDirectiveTrivia(ReferenceDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitLoadDirectiveTrivia(LoadDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
}

Expand Down Expand Up @@ -27216,6 +27307,7 @@ internal partial class CSharpSyntaxVisitor
public virtual void VisitReferenceDirectiveTrivia(ReferenceDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitLoadDirectiveTrivia(LoadDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
}

Expand Down Expand Up @@ -27953,6 +28045,9 @@ public override CSharpSyntaxNode VisitLoadDirectiveTrivia(LoadDirectiveTriviaSyn
public override CSharpSyntaxNode VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node)
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.ExclamationToken), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);

public override CSharpSyntaxNode VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node)
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.ColonToken), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);

public override CSharpSyntaxNode VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node)
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.NullableKeyword), (SyntaxToken)Visit(node.SettingToken), (SyntaxToken)Visit(node.TargetToken), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
}
Expand Down Expand Up @@ -33237,6 +33332,20 @@ public ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(SyntaxToken hashToken
return new ShebangDirectiveTriviaSyntax(SyntaxKind.ShebangDirectiveTrivia, hashToken, exclamationToken, endOfDirectiveToken, isActive, this.context);
}

public IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
#if DEBUG
if (hashToken == null) throw new ArgumentNullException(nameof(hashToken));
if (hashToken.Kind != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
if (colonToken == null) throw new ArgumentNullException(nameof(colonToken));
if (colonToken.Kind != SyntaxKind.ColonToken) throw new ArgumentException(nameof(colonToken));
if (endOfDirectiveToken == null) throw new ArgumentNullException(nameof(endOfDirectiveToken));
if (endOfDirectiveToken.Kind != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
#endif

return new IgnoredDirectiveTriviaSyntax(SyntaxKind.IgnoredDirectiveTrivia, hashToken, colonToken, endOfDirectiveToken, isActive, this.context);
}

public NullableDirectiveTriviaSyntax NullableDirectiveTrivia(SyntaxToken hashToken, SyntaxToken nullableKeyword, SyntaxToken settingToken, SyntaxToken? targetToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
#if DEBUG
Expand Down Expand Up @@ -38545,6 +38654,20 @@ public static ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(SyntaxToken ha
return new ShebangDirectiveTriviaSyntax(SyntaxKind.ShebangDirectiveTrivia, hashToken, exclamationToken, endOfDirectiveToken, isActive);
}

public static IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
#if DEBUG
if (hashToken == null) throw new ArgumentNullException(nameof(hashToken));
if (hashToken.Kind != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
if (colonToken == null) throw new ArgumentNullException(nameof(colonToken));
if (colonToken.Kind != SyntaxKind.ColonToken) throw new ArgumentException(nameof(colonToken));
if (endOfDirectiveToken == null) throw new ArgumentNullException(nameof(endOfDirectiveToken));
if (endOfDirectiveToken.Kind != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
#endif

return new IgnoredDirectiveTriviaSyntax(SyntaxKind.IgnoredDirectiveTrivia, hashToken, colonToken, endOfDirectiveToken, isActive);
}

public static NullableDirectiveTriviaSyntax NullableDirectiveTrivia(SyntaxToken hashToken, SyntaxToken nullableKeyword, SyntaxToken settingToken, SyntaxToken? targetToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
#if DEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,9 @@ public partial class CSharpSyntaxVisitor<TResult>
/// <summary>Called when the visitor visits a ShebangDirectiveTriviaSyntax node.</summary>
public virtual TResult? VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a IgnoredDirectiveTriviaSyntax node.</summary>
public virtual TResult? VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a NullableDirectiveTriviaSyntax node.</summary>
public virtual TResult? VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
}
Expand Down Expand Up @@ -1485,6 +1488,9 @@ public partial class CSharpSyntaxVisitor
/// <summary>Called when the visitor visits a ShebangDirectiveTriviaSyntax node.</summary>
public virtual void VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a IgnoredDirectiveTriviaSyntax node.</summary>
public virtual void VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);

/// <summary>Called when the visitor visits a NullableDirectiveTriviaSyntax node.</summary>
public virtual void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
}
Expand Down Expand Up @@ -2223,6 +2229,9 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor<SyntaxNode?>
public override SyntaxNode? VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node)
=> node.Update(VisitToken(node.HashToken), VisitToken(node.ExclamationToken), VisitToken(node.EndOfDirectiveToken), node.IsActive);

public override SyntaxNode? VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node)
=> node.Update(VisitToken(node.HashToken), VisitToken(node.ColonToken), VisitToken(node.EndOfDirectiveToken), node.IsActive);

public override SyntaxNode? VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node)
=> node.Update(VisitToken(node.HashToken), VisitToken(node.NullableKeyword), VisitToken(node.SettingToken), VisitToken(node.TargetToken), VisitToken(node.EndOfDirectiveToken), node.IsActive);
}
Expand Down Expand Up @@ -6511,6 +6520,19 @@ public static ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(SyntaxToken ha
public static ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(bool isActive)
=> SyntaxFactory.ShebangDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.ExclamationToken), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);

/// <summary>Creates a new IgnoredDirectiveTriviaSyntax instance.</summary>
public static IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
if (hashToken.Kind() != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
if (colonToken.Kind() != SyntaxKind.ColonToken) throw new ArgumentException(nameof(colonToken));
if (endOfDirectiveToken.Kind() != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
return (IgnoredDirectiveTriviaSyntax)Syntax.InternalSyntax.SyntaxFactory.IgnoredDirectiveTrivia((Syntax.InternalSyntax.SyntaxToken)hashToken.Node!, (Syntax.InternalSyntax.SyntaxToken)colonToken.Node!, (Syntax.InternalSyntax.SyntaxToken)endOfDirectiveToken.Node!, isActive).CreateRed();
}

/// <summary>Creates a new IgnoredDirectiveTriviaSyntax instance.</summary>
public static IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(bool isActive)
=> SyntaxFactory.IgnoredDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.ColonToken), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);

/// <summary>Creates a new NullableDirectiveTriviaSyntax instance.</summary>
public static NullableDirectiveTriviaSyntax NullableDirectiveTrivia(SyntaxToken hashToken, SyntaxToken nullableKeyword, SyntaxToken settingToken, SyntaxToken targetToken, SyntaxToken endOfDirectiveToken, bool isActive)
{
Expand Down
Loading