Skip to content

Commit ba50b56

Browse files
committed
Parse ignored directives
1 parent adc21be commit ba50b56

36 files changed

+1245
-49
lines changed

src/Compilers/CSharp/Portable/CSharpParseOptions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@ static void addSingleNamespaceParts(ArrayBuilder<ImmutableArray<string>> namespa
230230
}
231231
}
232232

233+
/// <summary>
234+
/// Used for parsing .cs file-based programs.
235+
/// </summary>
236+
/// <remarks>
237+
/// In this mode, ignored directives <c>#:</c> are allowed.
238+
/// </remarks>
239+
internal bool FileBasedProgram => Features.ContainsKey("FileBasedProgram");
240+
233241
internal override void ValidateOptions(ArrayBuilder<Diagnostic> builder)
234242
{
235243
ValidateOptions(builder, MessageProvider.Instance);

src/Compilers/CSharp/Portable/CSharpResources.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8071,4 +8071,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
80718071
<data name="ERR_PartialConstructorInitializer" xml:space="preserve">
80728072
<value>'{0}': only the implementing declaration of a partial constructor can have an initializer</value>
80738073
</data>
8074+
<data name="ERR_PPIgnoredFollowsToken" xml:space="preserve">
8075+
<value>'#:' directives cannot be after first token in file</value>
8076+
</data>
8077+
<data name="ERR_PPIgnoredNeedsFileBasedProgram" xml:space="preserve">
8078+
<value>'#:' directives can be only used in file-based programs ('/feature:FileBasedProgram')</value>
8079+
</data>
8080+
<data name="ERR_PPIgnoredFollowsIf" xml:space="preserve">
8081+
<value>'#:' directives cannot be after '#if'</value>
8082+
</data>
80748083
</root>

src/Compilers/CSharp/Portable/Errors/ErrorCode.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,13 +2369,19 @@ internal enum ErrorCode
23692369
ERR_PartialEventInitializer = 9279,
23702370
ERR_PartialConstructorInitializer = 9280,
23712371

2372+
ERR_PPIgnoredFollowsToken = 9281,
2373+
ERR_PPIgnoredNeedsFileBasedProgram = 9282,
2374+
ERR_PPIgnoredFollowsIf = 9283,
2375+
23722376
// Note: you will need to do the following after adding errors:
23732377
// 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
2378+
// 2) Add message to CSharpResources.resx
23742379

23752380
// Note: you will need to do the following after adding warnings:
23762381
// 1) Re-generate compiler code (eng\generate-compiler-code.cmd).
23772382
// 2) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
23782383
// 3) Update ErrorFacts.GetWarningLevel (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
23792384
// 4) Update DiagnosticTest.WarningLevel_2 (src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs)
2385+
// 5) Add message and '_Title' to CSharpResources.resx
23802386
}
23812387
}

src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,9 @@ or ErrorCode.ERR_PartialMemberDuplicateDefinition
24872487
or ErrorCode.ERR_PartialMemberDuplicateImplementation
24882488
or ErrorCode.ERR_PartialEventInitializer
24892489
or ErrorCode.ERR_PartialConstructorInitializer
2490+
or ErrorCode.ERR_PPIgnoredFollowsToken
2491+
or ErrorCode.ERR_PPIgnoredNeedsFileBasedProgram
2492+
or ErrorCode.ERR_PPIgnoredFollowsIf
24902493
=> false,
24912494
};
24922495
#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.

src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26365,6 +26365,96 @@ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
2636526365
=> new ShebangDirectiveTriviaSyntax(this.Kind, this.hashToken, this.exclamationToken, this.endOfDirectiveToken, this.isActive, GetDiagnostics(), annotations);
2636626366
}
2636726367

26368+
internal sealed partial class IgnoredDirectiveTriviaSyntax : DirectiveTriviaSyntax
26369+
{
26370+
internal readonly SyntaxToken hashToken;
26371+
internal readonly SyntaxToken colonToken;
26372+
internal readonly SyntaxToken endOfDirectiveToken;
26373+
internal readonly bool isActive;
26374+
26375+
internal IgnoredDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
26376+
: base(kind, diagnostics, annotations)
26377+
{
26378+
this.SlotCount = 3;
26379+
this.AdjustFlagsAndWidth(hashToken);
26380+
this.hashToken = hashToken;
26381+
this.AdjustFlagsAndWidth(colonToken);
26382+
this.colonToken = colonToken;
26383+
this.AdjustFlagsAndWidth(endOfDirectiveToken);
26384+
this.endOfDirectiveToken = endOfDirectiveToken;
26385+
this.isActive = isActive;
26386+
}
26387+
26388+
internal IgnoredDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive, SyntaxFactoryContext context)
26389+
: base(kind)
26390+
{
26391+
this.SetFactoryContext(context);
26392+
this.SlotCount = 3;
26393+
this.AdjustFlagsAndWidth(hashToken);
26394+
this.hashToken = hashToken;
26395+
this.AdjustFlagsAndWidth(colonToken);
26396+
this.colonToken = colonToken;
26397+
this.AdjustFlagsAndWidth(endOfDirectiveToken);
26398+
this.endOfDirectiveToken = endOfDirectiveToken;
26399+
this.isActive = isActive;
26400+
}
26401+
26402+
internal IgnoredDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
26403+
: base(kind)
26404+
{
26405+
this.SlotCount = 3;
26406+
this.AdjustFlagsAndWidth(hashToken);
26407+
this.hashToken = hashToken;
26408+
this.AdjustFlagsAndWidth(colonToken);
26409+
this.colonToken = colonToken;
26410+
this.AdjustFlagsAndWidth(endOfDirectiveToken);
26411+
this.endOfDirectiveToken = endOfDirectiveToken;
26412+
this.isActive = isActive;
26413+
}
26414+
26415+
public override SyntaxToken HashToken => this.hashToken;
26416+
public SyntaxToken ColonToken => this.colonToken;
26417+
public override SyntaxToken EndOfDirectiveToken => this.endOfDirectiveToken;
26418+
public override bool IsActive => this.isActive;
26419+
26420+
internal override GreenNode? GetSlot(int index)
26421+
=> index switch
26422+
{
26423+
0 => this.hashToken,
26424+
1 => this.colonToken,
26425+
2 => this.endOfDirectiveToken,
26426+
_ => null,
26427+
};
26428+
26429+
internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.IgnoredDirectiveTriviaSyntax(this, parent, position);
26430+
26431+
public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitIgnoredDirectiveTrivia(this);
26432+
public override TResult Accept<TResult>(CSharpSyntaxVisitor<TResult> visitor) => visitor.VisitIgnoredDirectiveTrivia(this);
26433+
26434+
public IgnoredDirectiveTriviaSyntax Update(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
26435+
{
26436+
if (hashToken != this.HashToken || colonToken != this.ColonToken || endOfDirectiveToken != this.EndOfDirectiveToken)
26437+
{
26438+
var newNode = SyntaxFactory.IgnoredDirectiveTrivia(hashToken, colonToken, endOfDirectiveToken, isActive);
26439+
var diags = GetDiagnostics();
26440+
if (diags?.Length > 0)
26441+
newNode = newNode.WithDiagnosticsGreen(diags);
26442+
var annotations = GetAnnotations();
26443+
if (annotations?.Length > 0)
26444+
newNode = newNode.WithAnnotationsGreen(annotations);
26445+
return newNode;
26446+
}
26447+
26448+
return this;
26449+
}
26450+
26451+
internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics)
26452+
=> new IgnoredDirectiveTriviaSyntax(this.Kind, this.hashToken, this.colonToken, this.endOfDirectiveToken, this.isActive, diagnostics, GetAnnotations());
26453+
26454+
internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
26455+
=> new IgnoredDirectiveTriviaSyntax(this.Kind, this.hashToken, this.colonToken, this.endOfDirectiveToken, this.isActive, GetDiagnostics(), annotations);
26456+
}
26457+
2636826458
internal sealed partial class NullableDirectiveTriviaSyntax : DirectiveTriviaSyntax
2636926459
{
2637026460
internal readonly SyntaxToken hashToken;
@@ -26727,6 +26817,7 @@ internal partial class CSharpSyntaxVisitor<TResult>
2672726817
public virtual TResult VisitReferenceDirectiveTrivia(ReferenceDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2672826818
public virtual TResult VisitLoadDirectiveTrivia(LoadDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2672926819
public virtual TResult VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);
26820+
public virtual TResult VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2673026821
public virtual TResult VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2673126822
}
2673226823

@@ -26975,6 +27066,7 @@ internal partial class CSharpSyntaxVisitor
2697527066
public virtual void VisitReferenceDirectiveTrivia(ReferenceDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2697627067
public virtual void VisitLoadDirectiveTrivia(LoadDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2697727068
public virtual void VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);
27069+
public virtual void VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2697827070
public virtual void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
2697927071
}
2698027072

@@ -27709,6 +27801,9 @@ public override CSharpSyntaxNode VisitLoadDirectiveTrivia(LoadDirectiveTriviaSyn
2770927801
public override CSharpSyntaxNode VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node)
2771027802
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.ExclamationToken), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
2771127803

27804+
public override CSharpSyntaxNode VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node)
27805+
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.ColonToken), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
27806+
2771227807
public override CSharpSyntaxNode VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node)
2771327808
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.NullableKeyword), (SyntaxToken)Visit(node.SettingToken), (SyntaxToken)Visit(node.TargetToken), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
2771427809
}
@@ -32953,6 +33048,20 @@ public ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(SyntaxToken hashToken
3295333048
return new ShebangDirectiveTriviaSyntax(SyntaxKind.ShebangDirectiveTrivia, hashToken, exclamationToken, endOfDirectiveToken, isActive, this.context);
3295433049
}
3295533050

33051+
public IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
33052+
{
33053+
#if DEBUG
33054+
if (hashToken == null) throw new ArgumentNullException(nameof(hashToken));
33055+
if (hashToken.Kind != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
33056+
if (colonToken == null) throw new ArgumentNullException(nameof(colonToken));
33057+
if (colonToken.Kind != SyntaxKind.ColonToken) throw new ArgumentException(nameof(colonToken));
33058+
if (endOfDirectiveToken == null) throw new ArgumentNullException(nameof(endOfDirectiveToken));
33059+
if (endOfDirectiveToken.Kind != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
33060+
#endif
33061+
33062+
return new IgnoredDirectiveTriviaSyntax(SyntaxKind.IgnoredDirectiveTrivia, hashToken, colonToken, endOfDirectiveToken, isActive, this.context);
33063+
}
33064+
3295633065
public NullableDirectiveTriviaSyntax NullableDirectiveTrivia(SyntaxToken hashToken, SyntaxToken nullableKeyword, SyntaxToken settingToken, SyntaxToken? targetToken, SyntaxToken endOfDirectiveToken, bool isActive)
3295733066
{
3295833067
#if DEBUG
@@ -38221,6 +38330,20 @@ public static ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(SyntaxToken ha
3822138330
return new ShebangDirectiveTriviaSyntax(SyntaxKind.ShebangDirectiveTrivia, hashToken, exclamationToken, endOfDirectiveToken, isActive);
3822238331
}
3822338332

38333+
public static IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
38334+
{
38335+
#if DEBUG
38336+
if (hashToken == null) throw new ArgumentNullException(nameof(hashToken));
38337+
if (hashToken.Kind != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
38338+
if (colonToken == null) throw new ArgumentNullException(nameof(colonToken));
38339+
if (colonToken.Kind != SyntaxKind.ColonToken) throw new ArgumentException(nameof(colonToken));
38340+
if (endOfDirectiveToken == null) throw new ArgumentNullException(nameof(endOfDirectiveToken));
38341+
if (endOfDirectiveToken.Kind != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
38342+
#endif
38343+
38344+
return new IgnoredDirectiveTriviaSyntax(SyntaxKind.IgnoredDirectiveTrivia, hashToken, colonToken, endOfDirectiveToken, isActive);
38345+
}
38346+
3822438347
public static NullableDirectiveTriviaSyntax NullableDirectiveTrivia(SyntaxToken hashToken, SyntaxToken nullableKeyword, SyntaxToken settingToken, SyntaxToken? targetToken, SyntaxToken endOfDirectiveToken, bool isActive)
3822538348
{
3822638349
#if DEBUG

src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,9 @@ public partial class CSharpSyntaxVisitor<TResult>
744744
/// <summary>Called when the visitor visits a ShebangDirectiveTriviaSyntax node.</summary>
745745
public virtual TResult? VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);
746746

747+
/// <summary>Called when the visitor visits a IgnoredDirectiveTriviaSyntax node.</summary>
748+
public virtual TResult? VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);
749+
747750
/// <summary>Called when the visitor visits a NullableDirectiveTriviaSyntax node.</summary>
748751
public virtual TResult? VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
749752
}
@@ -1479,6 +1482,9 @@ public partial class CSharpSyntaxVisitor
14791482
/// <summary>Called when the visitor visits a ShebangDirectiveTriviaSyntax node.</summary>
14801483
public virtual void VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node) => this.DefaultVisit(node);
14811484

1485+
/// <summary>Called when the visitor visits a IgnoredDirectiveTriviaSyntax node.</summary>
1486+
public virtual void VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node) => this.DefaultVisit(node);
1487+
14821488
/// <summary>Called when the visitor visits a NullableDirectiveTriviaSyntax node.</summary>
14831489
public virtual void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => this.DefaultVisit(node);
14841490
}
@@ -2214,6 +2220,9 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor<SyntaxNode?>
22142220
public override SyntaxNode? VisitShebangDirectiveTrivia(ShebangDirectiveTriviaSyntax node)
22152221
=> node.Update(VisitToken(node.HashToken), VisitToken(node.ExclamationToken), VisitToken(node.EndOfDirectiveToken), node.IsActive);
22162222

2223+
public override SyntaxNode? VisitIgnoredDirectiveTrivia(IgnoredDirectiveTriviaSyntax node)
2224+
=> node.Update(VisitToken(node.HashToken), VisitToken(node.ColonToken), VisitToken(node.EndOfDirectiveToken), node.IsActive);
2225+
22172226
public override SyntaxNode? VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node)
22182227
=> node.Update(VisitToken(node.HashToken), VisitToken(node.NullableKeyword), VisitToken(node.SettingToken), VisitToken(node.TargetToken), VisitToken(node.EndOfDirectiveToken), node.IsActive);
22192228
}
@@ -6480,6 +6489,19 @@ public static ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(SyntaxToken ha
64806489
public static ShebangDirectiveTriviaSyntax ShebangDirectiveTrivia(bool isActive)
64816490
=> SyntaxFactory.ShebangDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.ExclamationToken), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);
64826491

6492+
/// <summary>Creates a new IgnoredDirectiveTriviaSyntax instance.</summary>
6493+
public static IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(SyntaxToken hashToken, SyntaxToken colonToken, SyntaxToken endOfDirectiveToken, bool isActive)
6494+
{
6495+
if (hashToken.Kind() != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
6496+
if (colonToken.Kind() != SyntaxKind.ColonToken) throw new ArgumentException(nameof(colonToken));
6497+
if (endOfDirectiveToken.Kind() != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
6498+
return (IgnoredDirectiveTriviaSyntax)Syntax.InternalSyntax.SyntaxFactory.IgnoredDirectiveTrivia((Syntax.InternalSyntax.SyntaxToken)hashToken.Node!, (Syntax.InternalSyntax.SyntaxToken)colonToken.Node!, (Syntax.InternalSyntax.SyntaxToken)endOfDirectiveToken.Node!, isActive).CreateRed();
6499+
}
6500+
6501+
/// <summary>Creates a new IgnoredDirectiveTriviaSyntax instance.</summary>
6502+
public static IgnoredDirectiveTriviaSyntax IgnoredDirectiveTrivia(bool isActive)
6503+
=> SyntaxFactory.IgnoredDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.ColonToken), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);
6504+
64836505
/// <summary>Creates a new NullableDirectiveTriviaSyntax instance.</summary>
64846506
public static NullableDirectiveTriviaSyntax NullableDirectiveTrivia(SyntaxToken hashToken, SyntaxToken nullableKeyword, SyntaxToken settingToken, SyntaxToken targetToken, SyntaxToken endOfDirectiveToken, bool isActive)
64856507
{

0 commit comments

Comments
 (0)