diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 2e5a1dac19235..00140848865b4 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -6634,6 +6634,15 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
inferred delegate type
+
+ line span directive
+
+
+ The #line directive value is missing or out of range
+
+
+ The #line directive end position must be greater than or equal to the start position
+
Comparison of function pointers might yield an unexpected result, since pointers to the same function may be distinct.
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 16f5d833134d0..d13a861e65fbe 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -1960,6 +1960,8 @@ internal enum ErrorCode
ERR_BuilderAttributeDisallowed = 8935,
ERR_FeatureNotAvailableInVersion10 = 8936,
ERR_SimpleProgramIsEmpty = 8937,
+ ERR_LineSpanDirectiveInvalidValue = 8938,
+ ERR_LineSpanDirectiveEndLessThanStart = 8939,
#endregion
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
index 50a2a6dc96cda..65c413719f3a6 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
@@ -229,6 +229,7 @@ internal enum MessageID
IDS_FeatureLambdaReturnType = MessageBase + 12804,
IDS_AsyncMethodBuilderOverride = MessageBase + 12805,
IDS_FeatureImplicitImplementationOfNonPublicMemebers = MessageBase + 12806,
+ IDS_FeatureLineSpanDirective = MessageBase + 12807,
}
// Message IDs may refer to strings that need to be localized.
@@ -354,6 +355,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
case MessageID.IDS_AsyncMethodBuilderOverride: // semantic check
case MessageID.IDS_FeatureConstantInterpolatedStrings: // semantic check
case MessageID.IDS_FeatureImplicitImplementationOfNonPublicMemebers: // semantic check
+ case MessageID.IDS_FeatureLineSpanDirective:
return LanguageVersion.CSharp10;
// C# 9.0 features.
diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
index 089c1b1d58d3e..9450e00d62f58 100644
--- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
+++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
@@ -1180,7 +1180,7 @@ directive_trivia
| end_if_directive_trivia
| end_region_directive_trivia
| error_directive_trivia
- | line_directive_trivia
+ | line_or_span_directive_trivia
| load_directive_trivia
| nullable_directive_trivia
| pragma_checksum_directive_trivia
@@ -1234,10 +1234,23 @@ error_directive_trivia
: '#' 'error'
;
+line_or_span_directive_trivia
+ : line_directive_trivia
+ | line_span_directive_trivia
+ ;
+
line_directive_trivia
: '#' 'line' (numeric_literal_token | 'default' | 'hidden') string_literal_token?
;
+line_span_directive_trivia
+ : '#' 'line' line_directive_position '-' line_directive_position numeric_literal_token? string_literal_token
+ ;
+
+line_directive_position
+ : '(' numeric_literal_token ',' numeric_literal_token ')'
+ ;
+
load_directive_trivia
: '#' 'load' string_literal_token
;
diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs
index 05a6ef6458e3f..091928df6b8dc 100644
--- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs
@@ -32208,7 +32208,29 @@ static UndefDirectiveTriviaSyntax()
}
}
- internal sealed partial class LineDirectiveTriviaSyntax : DirectiveTriviaSyntax
+ internal abstract partial class LineOrSpanDirectiveTriviaSyntax : DirectiveTriviaSyntax
+ {
+ internal LineOrSpanDirectiveTriviaSyntax(SyntaxKind kind, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
+ : base(kind, diagnostics, annotations)
+ {
+ }
+
+ internal LineOrSpanDirectiveTriviaSyntax(SyntaxKind kind)
+ : base(kind)
+ {
+ }
+
+ protected LineOrSpanDirectiveTriviaSyntax(ObjectReader reader)
+ : base(reader)
+ {
+ }
+
+ public abstract SyntaxToken LineKeyword { get; }
+
+ public abstract SyntaxToken? File { get; }
+ }
+
+ internal sealed partial class LineDirectiveTriviaSyntax : LineOrSpanDirectiveTriviaSyntax
{
internal readonly SyntaxToken hashToken;
internal readonly SyntaxToken lineKeyword;
@@ -32279,9 +32301,9 @@ internal LineDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, Synta
}
public override SyntaxToken HashToken => this.hashToken;
- public SyntaxToken LineKeyword => this.lineKeyword;
+ public override SyntaxToken LineKeyword => this.lineKeyword;
public SyntaxToken Line => this.line;
- public SyntaxToken? File => this.file;
+ public override SyntaxToken? File => this.file;
public override SyntaxToken EndOfDirectiveToken => this.endOfDirectiveToken;
public override bool IsActive => this.isActive;
@@ -32366,6 +32388,342 @@ static LineDirectiveTriviaSyntax()
}
}
+ internal sealed partial class LineDirectivePositionSyntax : CSharpSyntaxNode
+ {
+ internal readonly SyntaxToken openParenToken;
+ internal readonly SyntaxToken line;
+ internal readonly SyntaxToken commaToken;
+ internal readonly SyntaxToken character;
+ internal readonly SyntaxToken closeParenToken;
+
+ internal LineDirectivePositionSyntax(SyntaxKind kind, SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
+ : base(kind, diagnostics, annotations)
+ {
+ this.SlotCount = 5;
+ this.AdjustFlagsAndWidth(openParenToken);
+ this.openParenToken = openParenToken;
+ this.AdjustFlagsAndWidth(line);
+ this.line = line;
+ this.AdjustFlagsAndWidth(commaToken);
+ this.commaToken = commaToken;
+ this.AdjustFlagsAndWidth(character);
+ this.character = character;
+ this.AdjustFlagsAndWidth(closeParenToken);
+ this.closeParenToken = closeParenToken;
+ }
+
+ internal LineDirectivePositionSyntax(SyntaxKind kind, SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken, SyntaxFactoryContext context)
+ : base(kind)
+ {
+ this.SetFactoryContext(context);
+ this.SlotCount = 5;
+ this.AdjustFlagsAndWidth(openParenToken);
+ this.openParenToken = openParenToken;
+ this.AdjustFlagsAndWidth(line);
+ this.line = line;
+ this.AdjustFlagsAndWidth(commaToken);
+ this.commaToken = commaToken;
+ this.AdjustFlagsAndWidth(character);
+ this.character = character;
+ this.AdjustFlagsAndWidth(closeParenToken);
+ this.closeParenToken = closeParenToken;
+ }
+
+ internal LineDirectivePositionSyntax(SyntaxKind kind, SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken)
+ : base(kind)
+ {
+ this.SlotCount = 5;
+ this.AdjustFlagsAndWidth(openParenToken);
+ this.openParenToken = openParenToken;
+ this.AdjustFlagsAndWidth(line);
+ this.line = line;
+ this.AdjustFlagsAndWidth(commaToken);
+ this.commaToken = commaToken;
+ this.AdjustFlagsAndWidth(character);
+ this.character = character;
+ this.AdjustFlagsAndWidth(closeParenToken);
+ this.closeParenToken = closeParenToken;
+ }
+
+ public SyntaxToken OpenParenToken => this.openParenToken;
+ public SyntaxToken Line => this.line;
+ public SyntaxToken CommaToken => this.commaToken;
+ public SyntaxToken Character => this.character;
+ public SyntaxToken CloseParenToken => this.closeParenToken;
+
+ internal override GreenNode? GetSlot(int index)
+ => index switch
+ {
+ 0 => this.openParenToken,
+ 1 => this.line,
+ 2 => this.commaToken,
+ 3 => this.character,
+ 4 => this.closeParenToken,
+ _ => null,
+ };
+
+ internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.LineDirectivePositionSyntax(this, parent, position);
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLineDirectivePosition(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLineDirectivePosition(this);
+
+ public LineDirectivePositionSyntax Update(SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken)
+ {
+ if (openParenToken != this.OpenParenToken || line != this.Line || commaToken != this.CommaToken || character != this.Character || closeParenToken != this.CloseParenToken)
+ {
+ var newNode = SyntaxFactory.LineDirectivePosition(openParenToken, line, commaToken, character, closeParenToken);
+ 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 LineDirectivePositionSyntax(this.Kind, this.openParenToken, this.line, this.commaToken, this.character, this.closeParenToken, diagnostics, GetAnnotations());
+
+ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
+ => new LineDirectivePositionSyntax(this.Kind, this.openParenToken, this.line, this.commaToken, this.character, this.closeParenToken, GetDiagnostics(), annotations);
+
+ internal LineDirectivePositionSyntax(ObjectReader reader)
+ : base(reader)
+ {
+ this.SlotCount = 5;
+ var openParenToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(openParenToken);
+ this.openParenToken = openParenToken;
+ var line = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(line);
+ this.line = line;
+ var commaToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(commaToken);
+ this.commaToken = commaToken;
+ var character = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(character);
+ this.character = character;
+ var closeParenToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(closeParenToken);
+ this.closeParenToken = closeParenToken;
+ }
+
+ internal override void WriteTo(ObjectWriter writer)
+ {
+ base.WriteTo(writer);
+ writer.WriteValue(this.openParenToken);
+ writer.WriteValue(this.line);
+ writer.WriteValue(this.commaToken);
+ writer.WriteValue(this.character);
+ writer.WriteValue(this.closeParenToken);
+ }
+
+ static LineDirectivePositionSyntax()
+ {
+ ObjectBinder.RegisterTypeReader(typeof(LineDirectivePositionSyntax), r => new LineDirectivePositionSyntax(r));
+ }
+ }
+
+ internal sealed partial class LineSpanDirectiveTriviaSyntax : LineOrSpanDirectiveTriviaSyntax
+ {
+ internal readonly SyntaxToken hashToken;
+ internal readonly SyntaxToken lineKeyword;
+ internal readonly LineDirectivePositionSyntax start;
+ internal readonly SyntaxToken minusToken;
+ internal readonly LineDirectivePositionSyntax end;
+ internal readonly SyntaxToken? characterOffset;
+ internal readonly SyntaxToken file;
+ internal readonly SyntaxToken endOfDirectiveToken;
+ internal readonly bool isActive;
+
+ internal LineSpanDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken? characterOffset, SyntaxToken file, SyntaxToken endOfDirectiveToken, bool isActive, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations)
+ : base(kind, diagnostics, annotations)
+ {
+ this.SlotCount = 8;
+ this.AdjustFlagsAndWidth(hashToken);
+ this.hashToken = hashToken;
+ this.AdjustFlagsAndWidth(lineKeyword);
+ this.lineKeyword = lineKeyword;
+ this.AdjustFlagsAndWidth(start);
+ this.start = start;
+ this.AdjustFlagsAndWidth(minusToken);
+ this.minusToken = minusToken;
+ this.AdjustFlagsAndWidth(end);
+ this.end = end;
+ if (characterOffset != null)
+ {
+ this.AdjustFlagsAndWidth(characterOffset);
+ this.characterOffset = characterOffset;
+ }
+ this.AdjustFlagsAndWidth(file);
+ this.file = file;
+ this.AdjustFlagsAndWidth(endOfDirectiveToken);
+ this.endOfDirectiveToken = endOfDirectiveToken;
+ this.isActive = isActive;
+ }
+
+ internal LineSpanDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken? characterOffset, SyntaxToken file, SyntaxToken endOfDirectiveToken, bool isActive, SyntaxFactoryContext context)
+ : base(kind)
+ {
+ this.SetFactoryContext(context);
+ this.SlotCount = 8;
+ this.AdjustFlagsAndWidth(hashToken);
+ this.hashToken = hashToken;
+ this.AdjustFlagsAndWidth(lineKeyword);
+ this.lineKeyword = lineKeyword;
+ this.AdjustFlagsAndWidth(start);
+ this.start = start;
+ this.AdjustFlagsAndWidth(minusToken);
+ this.minusToken = minusToken;
+ this.AdjustFlagsAndWidth(end);
+ this.end = end;
+ if (characterOffset != null)
+ {
+ this.AdjustFlagsAndWidth(characterOffset);
+ this.characterOffset = characterOffset;
+ }
+ this.AdjustFlagsAndWidth(file);
+ this.file = file;
+ this.AdjustFlagsAndWidth(endOfDirectiveToken);
+ this.endOfDirectiveToken = endOfDirectiveToken;
+ this.isActive = isActive;
+ }
+
+ internal LineSpanDirectiveTriviaSyntax(SyntaxKind kind, SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken? characterOffset, SyntaxToken file, SyntaxToken endOfDirectiveToken, bool isActive)
+ : base(kind)
+ {
+ this.SlotCount = 8;
+ this.AdjustFlagsAndWidth(hashToken);
+ this.hashToken = hashToken;
+ this.AdjustFlagsAndWidth(lineKeyword);
+ this.lineKeyword = lineKeyword;
+ this.AdjustFlagsAndWidth(start);
+ this.start = start;
+ this.AdjustFlagsAndWidth(minusToken);
+ this.minusToken = minusToken;
+ this.AdjustFlagsAndWidth(end);
+ this.end = end;
+ if (characterOffset != null)
+ {
+ this.AdjustFlagsAndWidth(characterOffset);
+ this.characterOffset = characterOffset;
+ }
+ this.AdjustFlagsAndWidth(file);
+ this.file = file;
+ this.AdjustFlagsAndWidth(endOfDirectiveToken);
+ this.endOfDirectiveToken = endOfDirectiveToken;
+ this.isActive = isActive;
+ }
+
+ public override SyntaxToken HashToken => this.hashToken;
+ public override SyntaxToken LineKeyword => this.lineKeyword;
+ public LineDirectivePositionSyntax Start => this.start;
+ public SyntaxToken MinusToken => this.minusToken;
+ public LineDirectivePositionSyntax End => this.end;
+ public SyntaxToken? CharacterOffset => this.characterOffset;
+ public override SyntaxToken File => this.file;
+ 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.lineKeyword,
+ 2 => this.start,
+ 3 => this.minusToken,
+ 4 => this.end,
+ 5 => this.characterOffset,
+ 6 => this.file,
+ 7 => this.endOfDirectiveToken,
+ _ => null,
+ };
+
+ internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.LineSpanDirectiveTriviaSyntax(this, parent, position);
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLineSpanDirectiveTrivia(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLineSpanDirectiveTrivia(this);
+
+ public LineSpanDirectiveTriviaSyntax Update(SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken characterOffset, SyntaxToken file, SyntaxToken endOfDirectiveToken, bool isActive)
+ {
+ if (hashToken != this.HashToken || lineKeyword != this.LineKeyword || start != this.Start || minusToken != this.MinusToken || end != this.End || characterOffset != this.CharacterOffset || file != this.File || endOfDirectiveToken != this.EndOfDirectiveToken)
+ {
+ var newNode = SyntaxFactory.LineSpanDirectiveTrivia(hashToken, lineKeyword, start, minusToken, end, characterOffset, file, 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 LineSpanDirectiveTriviaSyntax(this.Kind, this.hashToken, this.lineKeyword, this.start, this.minusToken, this.end, this.characterOffset, this.file, this.endOfDirectiveToken, this.isActive, diagnostics, GetAnnotations());
+
+ internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations)
+ => new LineSpanDirectiveTriviaSyntax(this.Kind, this.hashToken, this.lineKeyword, this.start, this.minusToken, this.end, this.characterOffset, this.file, this.endOfDirectiveToken, this.isActive, GetDiagnostics(), annotations);
+
+ internal LineSpanDirectiveTriviaSyntax(ObjectReader reader)
+ : base(reader)
+ {
+ this.SlotCount = 8;
+ var hashToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(hashToken);
+ this.hashToken = hashToken;
+ var lineKeyword = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(lineKeyword);
+ this.lineKeyword = lineKeyword;
+ var start = (LineDirectivePositionSyntax)reader.ReadValue();
+ AdjustFlagsAndWidth(start);
+ this.start = start;
+ var minusToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(minusToken);
+ this.minusToken = minusToken;
+ var end = (LineDirectivePositionSyntax)reader.ReadValue();
+ AdjustFlagsAndWidth(end);
+ this.end = end;
+ var characterOffset = (SyntaxToken?)reader.ReadValue();
+ if (characterOffset != null)
+ {
+ AdjustFlagsAndWidth(characterOffset);
+ this.characterOffset = characterOffset;
+ }
+ var file = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(file);
+ this.file = file;
+ var endOfDirectiveToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(endOfDirectiveToken);
+ this.endOfDirectiveToken = endOfDirectiveToken;
+ this.isActive = (bool)reader.ReadBoolean();
+ }
+
+ internal override void WriteTo(ObjectWriter writer)
+ {
+ base.WriteTo(writer);
+ writer.WriteValue(this.hashToken);
+ writer.WriteValue(this.lineKeyword);
+ writer.WriteValue(this.start);
+ writer.WriteValue(this.minusToken);
+ writer.WriteValue(this.end);
+ writer.WriteValue(this.characterOffset);
+ writer.WriteValue(this.file);
+ writer.WriteValue(this.endOfDirectiveToken);
+ writer.WriteBoolean(this.isActive);
+ }
+
+ static LineSpanDirectiveTriviaSyntax()
+ {
+ ObjectBinder.RegisterTypeReader(typeof(LineSpanDirectiveTriviaSyntax), r => new LineSpanDirectiveTriviaSyntax(r));
+ }
+ }
+
internal sealed partial class PragmaWarningDirectiveTriviaSyntax : DirectiveTriviaSyntax
{
internal readonly SyntaxToken hashToken;
@@ -33481,6 +33839,8 @@ internal partial class CSharpSyntaxVisitor
public virtual TResult VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) => this.DefaultVisit(node);
+ public virtual TResult VisitLineDirectivePosition(LineDirectivePositionSyntax node) => this.DefaultVisit(node);
+ public virtual TResult VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitReferenceDirectiveTrivia(ReferenceDirectiveTriviaSyntax node) => this.DefaultVisit(node);
@@ -33717,6 +34077,8 @@ internal partial class CSharpSyntaxVisitor
public virtual void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) => this.DefaultVisit(node);
+ public virtual void VisitLineDirectivePosition(LineDirectivePositionSyntax node) => this.DefaultVisit(node);
+ public virtual void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node) => this.DefaultVisit(node);
public virtual void VisitReferenceDirectiveTrivia(ReferenceDirectiveTriviaSyntax node) => this.DefaultVisit(node);
@@ -34405,6 +34767,12 @@ public override CSharpSyntaxNode VisitUndefDirectiveTrivia(UndefDirectiveTriviaS
public override CSharpSyntaxNode VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node)
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.LineKeyword), (SyntaxToken)Visit(node.Line), (SyntaxToken)Visit(node.File), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
+ public override CSharpSyntaxNode VisitLineDirectivePosition(LineDirectivePositionSyntax node)
+ => node.Update((SyntaxToken)Visit(node.OpenParenToken), (SyntaxToken)Visit(node.Line), (SyntaxToken)Visit(node.CommaToken), (SyntaxToken)Visit(node.Character), (SyntaxToken)Visit(node.CloseParenToken));
+
+ public override CSharpSyntaxNode VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node)
+ => node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.LineKeyword), (LineDirectivePositionSyntax)Visit(node.Start), (SyntaxToken)Visit(node.MinusToken), (LineDirectivePositionSyntax)Visit(node.End), (SyntaxToken)Visit(node.CharacterOffset), (SyntaxToken)Visit(node.File), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
+
public override CSharpSyntaxNode VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node)
=> node.Update((SyntaxToken)Visit(node.HashToken), (SyntaxToken)Visit(node.PragmaKeyword), (SyntaxToken)Visit(node.WarningKeyword), (SyntaxToken)Visit(node.DisableOrRestoreKeyword), VisitList(node.ErrorCodes), (SyntaxToken)Visit(node.EndOfDirectiveToken), node.IsActive);
@@ -39218,6 +39586,53 @@ public LineDirectiveTriviaSyntax LineDirectiveTrivia(SyntaxToken hashToken, Synt
return new LineDirectiveTriviaSyntax(SyntaxKind.LineDirectiveTrivia, hashToken, lineKeyword, line, file, endOfDirectiveToken, isActive, this.context);
}
+ public LineDirectivePositionSyntax LineDirectivePosition(SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken)
+ {
+#if DEBUG
+ if (openParenToken == null) throw new ArgumentNullException(nameof(openParenToken));
+ if (openParenToken.Kind != SyntaxKind.OpenParenToken) throw new ArgumentException(nameof(openParenToken));
+ if (line == null) throw new ArgumentNullException(nameof(line));
+ if (line.Kind != SyntaxKind.NumericLiteralToken) throw new ArgumentException(nameof(line));
+ if (commaToken == null) throw new ArgumentNullException(nameof(commaToken));
+ if (commaToken.Kind != SyntaxKind.CommaToken) throw new ArgumentException(nameof(commaToken));
+ if (character == null) throw new ArgumentNullException(nameof(character));
+ if (character.Kind != SyntaxKind.NumericLiteralToken) throw new ArgumentException(nameof(character));
+ if (closeParenToken == null) throw new ArgumentNullException(nameof(closeParenToken));
+ if (closeParenToken.Kind != SyntaxKind.CloseParenToken) throw new ArgumentException(nameof(closeParenToken));
+#endif
+
+ return new LineDirectivePositionSyntax(SyntaxKind.LineDirectivePosition, openParenToken, line, commaToken, character, closeParenToken, this.context);
+ }
+
+ public LineSpanDirectiveTriviaSyntax LineSpanDirectiveTrivia(SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken? characterOffset, SyntaxToken file, 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 (lineKeyword == null) throw new ArgumentNullException(nameof(lineKeyword));
+ if (lineKeyword.Kind != SyntaxKind.LineKeyword) throw new ArgumentException(nameof(lineKeyword));
+ if (start == null) throw new ArgumentNullException(nameof(start));
+ if (minusToken == null) throw new ArgumentNullException(nameof(minusToken));
+ if (minusToken.Kind != SyntaxKind.MinusToken) throw new ArgumentException(nameof(minusToken));
+ if (end == null) throw new ArgumentNullException(nameof(end));
+ if (characterOffset != null)
+ {
+ switch (characterOffset.Kind)
+ {
+ case SyntaxKind.NumericLiteralToken:
+ case SyntaxKind.None: break;
+ default: throw new ArgumentException(nameof(characterOffset));
+ }
+ }
+ if (file == null) throw new ArgumentNullException(nameof(file));
+ if (file.Kind != SyntaxKind.StringLiteralToken) throw new ArgumentException(nameof(file));
+ if (endOfDirectiveToken == null) throw new ArgumentNullException(nameof(endOfDirectiveToken));
+ if (endOfDirectiveToken.Kind != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
+#endif
+
+ return new LineSpanDirectiveTriviaSyntax(SyntaxKind.LineSpanDirectiveTrivia, hashToken, lineKeyword, start, minusToken, end, characterOffset, file, endOfDirectiveToken, isActive, this.context);
+ }
+
public PragmaWarningDirectiveTriviaSyntax PragmaWarningDirectiveTrivia(SyntaxToken hashToken, SyntaxToken pragmaKeyword, SyntaxToken warningKeyword, SyntaxToken disableOrRestoreKeyword, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList errorCodes, SyntaxToken endOfDirectiveToken, bool isActive)
{
#if DEBUG
@@ -44131,6 +44546,53 @@ public static LineDirectiveTriviaSyntax LineDirectiveTrivia(SyntaxToken hashToke
return new LineDirectiveTriviaSyntax(SyntaxKind.LineDirectiveTrivia, hashToken, lineKeyword, line, file, endOfDirectiveToken, isActive);
}
+ public static LineDirectivePositionSyntax LineDirectivePosition(SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken)
+ {
+#if DEBUG
+ if (openParenToken == null) throw new ArgumentNullException(nameof(openParenToken));
+ if (openParenToken.Kind != SyntaxKind.OpenParenToken) throw new ArgumentException(nameof(openParenToken));
+ if (line == null) throw new ArgumentNullException(nameof(line));
+ if (line.Kind != SyntaxKind.NumericLiteralToken) throw new ArgumentException(nameof(line));
+ if (commaToken == null) throw new ArgumentNullException(nameof(commaToken));
+ if (commaToken.Kind != SyntaxKind.CommaToken) throw new ArgumentException(nameof(commaToken));
+ if (character == null) throw new ArgumentNullException(nameof(character));
+ if (character.Kind != SyntaxKind.NumericLiteralToken) throw new ArgumentException(nameof(character));
+ if (closeParenToken == null) throw new ArgumentNullException(nameof(closeParenToken));
+ if (closeParenToken.Kind != SyntaxKind.CloseParenToken) throw new ArgumentException(nameof(closeParenToken));
+#endif
+
+ return new LineDirectivePositionSyntax(SyntaxKind.LineDirectivePosition, openParenToken, line, commaToken, character, closeParenToken);
+ }
+
+ public static LineSpanDirectiveTriviaSyntax LineSpanDirectiveTrivia(SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken? characterOffset, SyntaxToken file, 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 (lineKeyword == null) throw new ArgumentNullException(nameof(lineKeyword));
+ if (lineKeyword.Kind != SyntaxKind.LineKeyword) throw new ArgumentException(nameof(lineKeyword));
+ if (start == null) throw new ArgumentNullException(nameof(start));
+ if (minusToken == null) throw new ArgumentNullException(nameof(minusToken));
+ if (minusToken.Kind != SyntaxKind.MinusToken) throw new ArgumentException(nameof(minusToken));
+ if (end == null) throw new ArgumentNullException(nameof(end));
+ if (characterOffset != null)
+ {
+ switch (characterOffset.Kind)
+ {
+ case SyntaxKind.NumericLiteralToken:
+ case SyntaxKind.None: break;
+ default: throw new ArgumentException(nameof(characterOffset));
+ }
+ }
+ if (file == null) throw new ArgumentNullException(nameof(file));
+ if (file.Kind != SyntaxKind.StringLiteralToken) throw new ArgumentException(nameof(file));
+ if (endOfDirectiveToken == null) throw new ArgumentNullException(nameof(endOfDirectiveToken));
+ if (endOfDirectiveToken.Kind != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
+#endif
+
+ return new LineSpanDirectiveTriviaSyntax(SyntaxKind.LineSpanDirectiveTrivia, hashToken, lineKeyword, start, minusToken, end, characterOffset, file, endOfDirectiveToken, isActive);
+ }
+
public static PragmaWarningDirectiveTriviaSyntax PragmaWarningDirectiveTrivia(SyntaxToken hashToken, SyntaxToken pragmaKeyword, SyntaxToken warningKeyword, SyntaxToken disableOrRestoreKeyword, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList errorCodes, SyntaxToken endOfDirectiveToken, bool isActive)
{
#if DEBUG
@@ -44483,6 +44945,8 @@ internal static IEnumerable GetNodeTypes()
typeof(DefineDirectiveTriviaSyntax),
typeof(UndefDirectiveTriviaSyntax),
typeof(LineDirectiveTriviaSyntax),
+ typeof(LineDirectivePositionSyntax),
+ typeof(LineSpanDirectiveTriviaSyntax),
typeof(PragmaWarningDirectiveTriviaSyntax),
typeof(PragmaChecksumDirectiveTriviaSyntax),
typeof(ReferenceDirectiveTriviaSyntax),
diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs
index 10c143022e4ce..055f9fbf7187b 100644
--- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs
@@ -693,6 +693,12 @@ public partial class CSharpSyntaxVisitor
/// Called when the visitor visits a LineDirectiveTriviaSyntax node.
public virtual TResult? VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) => this.DefaultVisit(node);
+ /// Called when the visitor visits a LineDirectivePositionSyntax node.
+ public virtual TResult? VisitLineDirectivePosition(LineDirectivePositionSyntax node) => this.DefaultVisit(node);
+
+ /// Called when the visitor visits a LineSpanDirectiveTriviaSyntax node.
+ public virtual TResult? VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) => this.DefaultVisit(node);
+
/// Called when the visitor visits a PragmaWarningDirectiveTriviaSyntax node.
public virtual TResult? VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) => this.DefaultVisit(node);
@@ -1392,6 +1398,12 @@ public partial class CSharpSyntaxVisitor
/// Called when the visitor visits a LineDirectiveTriviaSyntax node.
public virtual void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) => this.DefaultVisit(node);
+ /// Called when the visitor visits a LineDirectivePositionSyntax node.
+ public virtual void VisitLineDirectivePosition(LineDirectivePositionSyntax node) => this.DefaultVisit(node);
+
+ /// Called when the visitor visits a LineSpanDirectiveTriviaSyntax node.
+ public virtual void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) => this.DefaultVisit(node);
+
/// Called when the visitor visits a PragmaWarningDirectiveTriviaSyntax node.
public virtual void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) => this.DefaultVisit(node);
@@ -2091,6 +2103,12 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor
public override SyntaxNode? VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node)
=> node.Update(VisitToken(node.HashToken), VisitToken(node.LineKeyword), VisitToken(node.Line), VisitToken(node.File), VisitToken(node.EndOfDirectiveToken), node.IsActive);
+ public override SyntaxNode? VisitLineDirectivePosition(LineDirectivePositionSyntax node)
+ => node.Update(VisitToken(node.OpenParenToken), VisitToken(node.Line), VisitToken(node.CommaToken), VisitToken(node.Character), VisitToken(node.CloseParenToken));
+
+ public override SyntaxNode? VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node)
+ => node.Update(VisitToken(node.HashToken), VisitToken(node.LineKeyword), (LineDirectivePositionSyntax?)Visit(node.Start) ?? throw new ArgumentNullException("start"), VisitToken(node.MinusToken), (LineDirectivePositionSyntax?)Visit(node.End) ?? throw new ArgumentNullException("end"), VisitToken(node.CharacterOffset), VisitToken(node.File), VisitToken(node.EndOfDirectiveToken), node.IsActive);
+
public override SyntaxNode? VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node)
=> node.Update(VisitToken(node.HashToken), VisitToken(node.PragmaKeyword), VisitToken(node.WarningKeyword), VisitToken(node.DisableOrRestoreKeyword), VisitList(node.ErrorCodes), VisitToken(node.EndOfDirectiveToken), node.IsActive);
@@ -6090,6 +6108,48 @@ public static LineDirectiveTriviaSyntax LineDirectiveTrivia(SyntaxToken line, Sy
public static LineDirectiveTriviaSyntax LineDirectiveTrivia(SyntaxToken line, bool isActive)
=> SyntaxFactory.LineDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.LineKeyword), line, default, SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);
+ /// Creates a new LineDirectivePositionSyntax instance.
+ public static LineDirectivePositionSyntax LineDirectivePosition(SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken)
+ {
+ if (openParenToken.Kind() != SyntaxKind.OpenParenToken) throw new ArgumentException(nameof(openParenToken));
+ if (line.Kind() != SyntaxKind.NumericLiteralToken) throw new ArgumentException(nameof(line));
+ if (commaToken.Kind() != SyntaxKind.CommaToken) throw new ArgumentException(nameof(commaToken));
+ if (character.Kind() != SyntaxKind.NumericLiteralToken) throw new ArgumentException(nameof(character));
+ if (closeParenToken.Kind() != SyntaxKind.CloseParenToken) throw new ArgumentException(nameof(closeParenToken));
+ return (LineDirectivePositionSyntax)Syntax.InternalSyntax.SyntaxFactory.LineDirectivePosition((Syntax.InternalSyntax.SyntaxToken)openParenToken.Node!, (Syntax.InternalSyntax.SyntaxToken)line.Node!, (Syntax.InternalSyntax.SyntaxToken)commaToken.Node!, (Syntax.InternalSyntax.SyntaxToken)character.Node!, (Syntax.InternalSyntax.SyntaxToken)closeParenToken.Node!).CreateRed();
+ }
+
+ /// Creates a new LineDirectivePositionSyntax instance.
+ public static LineDirectivePositionSyntax LineDirectivePosition(SyntaxToken line, SyntaxToken character)
+ => SyntaxFactory.LineDirectivePosition(SyntaxFactory.Token(SyntaxKind.OpenParenToken), line, SyntaxFactory.Token(SyntaxKind.CommaToken), character, SyntaxFactory.Token(SyntaxKind.CloseParenToken));
+
+ /// Creates a new LineSpanDirectiveTriviaSyntax instance.
+ public static LineSpanDirectiveTriviaSyntax LineSpanDirectiveTrivia(SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken characterOffset, SyntaxToken file, SyntaxToken endOfDirectiveToken, bool isActive)
+ {
+ if (hashToken.Kind() != SyntaxKind.HashToken) throw new ArgumentException(nameof(hashToken));
+ if (lineKeyword.Kind() != SyntaxKind.LineKeyword) throw new ArgumentException(nameof(lineKeyword));
+ if (start == null) throw new ArgumentNullException(nameof(start));
+ if (minusToken.Kind() != SyntaxKind.MinusToken) throw new ArgumentException(nameof(minusToken));
+ if (end == null) throw new ArgumentNullException(nameof(end));
+ switch (characterOffset.Kind())
+ {
+ case SyntaxKind.NumericLiteralToken:
+ case SyntaxKind.None: break;
+ default: throw new ArgumentException(nameof(characterOffset));
+ }
+ if (file.Kind() != SyntaxKind.StringLiteralToken) throw new ArgumentException(nameof(file));
+ if (endOfDirectiveToken.Kind() != SyntaxKind.EndOfDirectiveToken) throw new ArgumentException(nameof(endOfDirectiveToken));
+ return (LineSpanDirectiveTriviaSyntax)Syntax.InternalSyntax.SyntaxFactory.LineSpanDirectiveTrivia((Syntax.InternalSyntax.SyntaxToken)hashToken.Node!, (Syntax.InternalSyntax.SyntaxToken)lineKeyword.Node!, (Syntax.InternalSyntax.LineDirectivePositionSyntax)start.Green, (Syntax.InternalSyntax.SyntaxToken)minusToken.Node!, (Syntax.InternalSyntax.LineDirectivePositionSyntax)end.Green, (Syntax.InternalSyntax.SyntaxToken?)characterOffset.Node, (Syntax.InternalSyntax.SyntaxToken)file.Node!, (Syntax.InternalSyntax.SyntaxToken)endOfDirectiveToken.Node!, isActive).CreateRed();
+ }
+
+ /// Creates a new LineSpanDirectiveTriviaSyntax instance.
+ public static LineSpanDirectiveTriviaSyntax LineSpanDirectiveTrivia(LineDirectivePositionSyntax start, LineDirectivePositionSyntax end, SyntaxToken characterOffset, SyntaxToken file, bool isActive)
+ => SyntaxFactory.LineSpanDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.LineKeyword), start, SyntaxFactory.Token(SyntaxKind.MinusToken), end, characterOffset, file, SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);
+
+ /// Creates a new LineSpanDirectiveTriviaSyntax instance.
+ public static LineSpanDirectiveTriviaSyntax LineSpanDirectiveTrivia(LineDirectivePositionSyntax start, LineDirectivePositionSyntax end, SyntaxToken file, bool isActive)
+ => SyntaxFactory.LineSpanDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.LineKeyword), start, SyntaxFactory.Token(SyntaxKind.MinusToken), end, default, file, SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), isActive);
+
/// Creates a new PragmaWarningDirectiveTriviaSyntax instance.
public static PragmaWarningDirectiveTriviaSyntax PragmaWarningDirectiveTrivia(SyntaxToken hashToken, SyntaxToken pragmaKeyword, SyntaxToken warningKeyword, SyntaxToken disableOrRestoreKeyword, SeparatedSyntaxList errorCodes, SyntaxToken endOfDirectiveToken, bool isActive)
{
diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs
index 26972dcd57d15..042ac762357c0 100644
--- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs
@@ -15138,13 +15138,32 @@ public UndefDirectiveTriviaSyntax Update(SyntaxToken hashToken, SyntaxToken unde
public UndefDirectiveTriviaSyntax WithIsActive(bool isActive) => Update(this.HashToken, this.UndefKeyword, this.Name, this.EndOfDirectiveToken, isActive);
}
+ public abstract partial class LineOrSpanDirectiveTriviaSyntax : DirectiveTriviaSyntax
+ {
+ internal LineOrSpanDirectiveTriviaSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
+ : base(green, parent, position)
+ {
+ }
+
+ public abstract SyntaxToken LineKeyword { get; }
+ public LineOrSpanDirectiveTriviaSyntax WithLineKeyword(SyntaxToken lineKeyword) => WithLineKeywordCore(lineKeyword);
+ internal abstract LineOrSpanDirectiveTriviaSyntax WithLineKeywordCore(SyntaxToken lineKeyword);
+
+ public abstract SyntaxToken File { get; }
+ public LineOrSpanDirectiveTriviaSyntax WithFile(SyntaxToken file) => WithFileCore(file);
+ internal abstract LineOrSpanDirectiveTriviaSyntax WithFileCore(SyntaxToken file);
+
+ public new LineOrSpanDirectiveTriviaSyntax WithHashToken(SyntaxToken hashToken) => (LineOrSpanDirectiveTriviaSyntax)WithHashTokenCore(hashToken);
+ public new LineOrSpanDirectiveTriviaSyntax WithEndOfDirectiveToken(SyntaxToken endOfDirectiveToken) => (LineOrSpanDirectiveTriviaSyntax)WithEndOfDirectiveTokenCore(endOfDirectiveToken);
+ }
+
///
/// This node is associated with the following syntax kinds:
///
///
///
///
- public sealed partial class LineDirectiveTriviaSyntax : DirectiveTriviaSyntax
+ public sealed partial class LineDirectiveTriviaSyntax : LineOrSpanDirectiveTriviaSyntax
{
internal LineDirectiveTriviaSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
@@ -15154,11 +15173,11 @@ internal LineDirectiveTriviaSyntax(InternalSyntax.CSharpSyntaxNode green, Syntax
public override SyntaxToken HashToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectiveTriviaSyntax)this.Green).hashToken, Position, 0);
- public SyntaxToken LineKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectiveTriviaSyntax)this.Green).lineKeyword, GetChildPosition(1), GetChildIndex(1));
+ public override SyntaxToken LineKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectiveTriviaSyntax)this.Green).lineKeyword, GetChildPosition(1), GetChildIndex(1));
public SyntaxToken Line => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectiveTriviaSyntax)this.Green).line, GetChildPosition(2), GetChildIndex(2));
- public SyntaxToken File
+ public override SyntaxToken File
{
get
{
@@ -15192,14 +15211,153 @@ public LineDirectiveTriviaSyntax Update(SyntaxToken hashToken, SyntaxToken lineK
internal override DirectiveTriviaSyntax WithHashTokenCore(SyntaxToken hashToken) => WithHashToken(hashToken);
public new LineDirectiveTriviaSyntax WithHashToken(SyntaxToken hashToken) => Update(hashToken, this.LineKeyword, this.Line, this.File, this.EndOfDirectiveToken, this.IsActive);
- public LineDirectiveTriviaSyntax WithLineKeyword(SyntaxToken lineKeyword) => Update(this.HashToken, lineKeyword, this.Line, this.File, this.EndOfDirectiveToken, this.IsActive);
+ internal override LineOrSpanDirectiveTriviaSyntax WithLineKeywordCore(SyntaxToken lineKeyword) => WithLineKeyword(lineKeyword);
+ public new LineDirectiveTriviaSyntax WithLineKeyword(SyntaxToken lineKeyword) => Update(this.HashToken, lineKeyword, this.Line, this.File, this.EndOfDirectiveToken, this.IsActive);
public LineDirectiveTriviaSyntax WithLine(SyntaxToken line) => Update(this.HashToken, this.LineKeyword, line, this.File, this.EndOfDirectiveToken, this.IsActive);
- public LineDirectiveTriviaSyntax WithFile(SyntaxToken file) => Update(this.HashToken, this.LineKeyword, this.Line, file, this.EndOfDirectiveToken, this.IsActive);
+ internal override LineOrSpanDirectiveTriviaSyntax WithFileCore(SyntaxToken file) => WithFile(file);
+ public new LineDirectiveTriviaSyntax WithFile(SyntaxToken file) => Update(this.HashToken, this.LineKeyword, this.Line, file, this.EndOfDirectiveToken, this.IsActive);
internal override DirectiveTriviaSyntax WithEndOfDirectiveTokenCore(SyntaxToken endOfDirectiveToken) => WithEndOfDirectiveToken(endOfDirectiveToken);
public new LineDirectiveTriviaSyntax WithEndOfDirectiveToken(SyntaxToken endOfDirectiveToken) => Update(this.HashToken, this.LineKeyword, this.Line, this.File, endOfDirectiveToken, this.IsActive);
public LineDirectiveTriviaSyntax WithIsActive(bool isActive) => Update(this.HashToken, this.LineKeyword, this.Line, this.File, this.EndOfDirectiveToken, isActive);
}
+ ///
+ /// This node is associated with the following syntax kinds:
+ ///
+ ///
+ ///
+ ///
+ public sealed partial class LineDirectivePositionSyntax : CSharpSyntaxNode
+ {
+
+ internal LineDirectivePositionSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
+ : base(green, parent, position)
+ {
+ }
+
+ public SyntaxToken OpenParenToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectivePositionSyntax)this.Green).openParenToken, Position, 0);
+
+ public SyntaxToken Line => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectivePositionSyntax)this.Green).line, GetChildPosition(1), GetChildIndex(1));
+
+ public SyntaxToken CommaToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectivePositionSyntax)this.Green).commaToken, GetChildPosition(2), GetChildIndex(2));
+
+ public SyntaxToken Character => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectivePositionSyntax)this.Green).character, GetChildPosition(3), GetChildIndex(3));
+
+ public SyntaxToken CloseParenToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineDirectivePositionSyntax)this.Green).closeParenToken, GetChildPosition(4), GetChildIndex(4));
+
+ internal override SyntaxNode? GetNodeSlot(int index) => null;
+
+ internal override SyntaxNode? GetCachedSlot(int index) => null;
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLineDirectivePosition(this);
+ public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitLineDirectivePosition(this);
+
+ public LineDirectivePositionSyntax Update(SyntaxToken openParenToken, SyntaxToken line, SyntaxToken commaToken, SyntaxToken character, SyntaxToken closeParenToken)
+ {
+ if (openParenToken != this.OpenParenToken || line != this.Line || commaToken != this.CommaToken || character != this.Character || closeParenToken != this.CloseParenToken)
+ {
+ var newNode = SyntaxFactory.LineDirectivePosition(openParenToken, line, commaToken, character, closeParenToken);
+ var annotations = GetAnnotations();
+ return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
+ }
+
+ return this;
+ }
+
+ public LineDirectivePositionSyntax WithOpenParenToken(SyntaxToken openParenToken) => Update(openParenToken, this.Line, this.CommaToken, this.Character, this.CloseParenToken);
+ public LineDirectivePositionSyntax WithLine(SyntaxToken line) => Update(this.OpenParenToken, line, this.CommaToken, this.Character, this.CloseParenToken);
+ public LineDirectivePositionSyntax WithCommaToken(SyntaxToken commaToken) => Update(this.OpenParenToken, this.Line, commaToken, this.Character, this.CloseParenToken);
+ public LineDirectivePositionSyntax WithCharacter(SyntaxToken character) => Update(this.OpenParenToken, this.Line, this.CommaToken, character, this.CloseParenToken);
+ public LineDirectivePositionSyntax WithCloseParenToken(SyntaxToken closeParenToken) => Update(this.OpenParenToken, this.Line, this.CommaToken, this.Character, closeParenToken);
+ }
+
+ ///
+ /// This node is associated with the following syntax kinds:
+ ///
+ ///
+ ///
+ ///
+ public sealed partial class LineSpanDirectiveTriviaSyntax : LineOrSpanDirectiveTriviaSyntax
+ {
+ private LineDirectivePositionSyntax? start;
+ private LineDirectivePositionSyntax? end;
+
+ internal LineSpanDirectiveTriviaSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
+ : base(green, parent, position)
+ {
+ }
+
+ public override SyntaxToken HashToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).hashToken, Position, 0);
+
+ public override SyntaxToken LineKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).lineKeyword, GetChildPosition(1), GetChildIndex(1));
+
+ public LineDirectivePositionSyntax Start => GetRed(ref this.start, 2)!;
+
+ public SyntaxToken MinusToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).minusToken, GetChildPosition(3), GetChildIndex(3));
+
+ public LineDirectivePositionSyntax End => GetRed(ref this.end, 4)!;
+
+ public SyntaxToken CharacterOffset
+ {
+ get
+ {
+ var slot = ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).characterOffset;
+ return slot != null ? new SyntaxToken(this, slot, GetChildPosition(5), GetChildIndex(5)) : default;
+ }
+ }
+
+ public override SyntaxToken File => new SyntaxToken(this, ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).file, GetChildPosition(6), GetChildIndex(6));
+
+ public override SyntaxToken EndOfDirectiveToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).endOfDirectiveToken, GetChildPosition(7), GetChildIndex(7));
+
+ public override bool IsActive => ((Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax)this.Green).IsActive;
+
+ internal override SyntaxNode? GetNodeSlot(int index)
+ => index switch
+ {
+ 2 => GetRed(ref this.start, 2)!,
+ 4 => GetRed(ref this.end, 4)!,
+ _ => null,
+ };
+
+ internal override SyntaxNode? GetCachedSlot(int index)
+ => index switch
+ {
+ 2 => this.start,
+ 4 => this.end,
+ _ => null,
+ };
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLineSpanDirectiveTrivia(this);
+ public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitLineSpanDirectiveTrivia(this);
+
+ public LineSpanDirectiveTriviaSyntax Update(SyntaxToken hashToken, SyntaxToken lineKeyword, LineDirectivePositionSyntax start, SyntaxToken minusToken, LineDirectivePositionSyntax end, SyntaxToken characterOffset, SyntaxToken file, SyntaxToken endOfDirectiveToken, bool isActive)
+ {
+ if (hashToken != this.HashToken || lineKeyword != this.LineKeyword || start != this.Start || minusToken != this.MinusToken || end != this.End || characterOffset != this.CharacterOffset || file != this.File || endOfDirectiveToken != this.EndOfDirectiveToken)
+ {
+ var newNode = SyntaxFactory.LineSpanDirectiveTrivia(hashToken, lineKeyword, start, minusToken, end, characterOffset, file, endOfDirectiveToken, isActive);
+ var annotations = GetAnnotations();
+ return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
+ }
+
+ return this;
+ }
+
+ internal override DirectiveTriviaSyntax WithHashTokenCore(SyntaxToken hashToken) => WithHashToken(hashToken);
+ public new LineSpanDirectiveTriviaSyntax WithHashToken(SyntaxToken hashToken) => Update(hashToken, this.LineKeyword, this.Start, this.MinusToken, this.End, this.CharacterOffset, this.File, this.EndOfDirectiveToken, this.IsActive);
+ internal override LineOrSpanDirectiveTriviaSyntax WithLineKeywordCore(SyntaxToken lineKeyword) => WithLineKeyword(lineKeyword);
+ public new LineSpanDirectiveTriviaSyntax WithLineKeyword(SyntaxToken lineKeyword) => Update(this.HashToken, lineKeyword, this.Start, this.MinusToken, this.End, this.CharacterOffset, this.File, this.EndOfDirectiveToken, this.IsActive);
+ public LineSpanDirectiveTriviaSyntax WithStart(LineDirectivePositionSyntax start) => Update(this.HashToken, this.LineKeyword, start, this.MinusToken, this.End, this.CharacterOffset, this.File, this.EndOfDirectiveToken, this.IsActive);
+ public LineSpanDirectiveTriviaSyntax WithMinusToken(SyntaxToken minusToken) => Update(this.HashToken, this.LineKeyword, this.Start, minusToken, this.End, this.CharacterOffset, this.File, this.EndOfDirectiveToken, this.IsActive);
+ public LineSpanDirectiveTriviaSyntax WithEnd(LineDirectivePositionSyntax end) => Update(this.HashToken, this.LineKeyword, this.Start, this.MinusToken, end, this.CharacterOffset, this.File, this.EndOfDirectiveToken, this.IsActive);
+ public LineSpanDirectiveTriviaSyntax WithCharacterOffset(SyntaxToken characterOffset) => Update(this.HashToken, this.LineKeyword, this.Start, this.MinusToken, this.End, characterOffset, this.File, this.EndOfDirectiveToken, this.IsActive);
+ internal override LineOrSpanDirectiveTriviaSyntax WithFileCore(SyntaxToken file) => WithFile(file);
+ public new LineSpanDirectiveTriviaSyntax WithFile(SyntaxToken file) => Update(this.HashToken, this.LineKeyword, this.Start, this.MinusToken, this.End, this.CharacterOffset, file, this.EndOfDirectiveToken, this.IsActive);
+ internal override DirectiveTriviaSyntax WithEndOfDirectiveTokenCore(SyntaxToken endOfDirectiveToken) => WithEndOfDirectiveToken(endOfDirectiveToken);
+ public new LineSpanDirectiveTriviaSyntax WithEndOfDirectiveToken(SyntaxToken endOfDirectiveToken) => Update(this.HashToken, this.LineKeyword, this.Start, this.MinusToken, this.End, this.CharacterOffset, this.File, endOfDirectiveToken, this.IsActive);
+ public LineSpanDirectiveTriviaSyntax WithIsActive(bool isActive) => Update(this.HashToken, this.LineKeyword, this.Start, this.MinusToken, this.End, this.CharacterOffset, this.File, this.EndOfDirectiveToken, isActive);
+ }
+
///
/// This node is associated with the following syntax kinds:
///
diff --git a/src/Compilers/CSharp/Portable/Parser/DirectiveParser.cs b/src/Compilers/CSharp/Portable/Parser/DirectiveParser.cs
index 5f507266f694c..066be0b8d5350 100644
--- a/src/Compilers/CSharp/Portable/Parser/DirectiveParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/DirectiveParser.cs
@@ -10,7 +10,6 @@
namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax
{
- using System.Reflection;
using Microsoft.CodeAnalysis.Syntax.InternalSyntax;
internal class DirectiveParser : SyntaxParser
@@ -87,7 +86,10 @@ public CSharpSyntaxNode ParseDirective(
break;
case SyntaxKind.LineKeyword:
- result = this.ParseLineDirective(hash, this.EatContextualToken(contextualKind), isActive);
+ var lineKeyword = this.EatContextualToken(contextualKind);
+ result = (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) ?
+ this.ParseLineSpanDirective(hash, lineKeyword, isActive) :
+ this.ParseLineDirective(hash, lineKeyword, isActive);
break;
case SyntaxKind.PragmaKeyword:
@@ -357,6 +359,9 @@ private DirectiveTriviaSyntax ParseErrorOrWarningDirective(SyntaxToken hash, Syn
}
}
+ private const int MaxLineValue = 0xfeefed;
+ private const int MaxCharacterValue = 0x10000;
+
private DirectiveTriviaSyntax ParseLineDirective(SyntaxToken hash, SyntaxToken id, bool isActive)
{
SyntaxToken line;
@@ -377,7 +382,7 @@ private DirectiveTriviaSyntax ParseLineDirective(SyntaxToken hash, SyntaxToken i
{
line = this.AddError(line, ErrorCode.ERR_InvalidLineNumber);
}
- else if ((int)line.Value > 0xfeefed)
+ else if ((int)line.Value > MaxLineValue)
{
line = this.AddError(line, ErrorCode.WRN_TooManyLinesForDebugger);
}
@@ -397,6 +402,77 @@ private DirectiveTriviaSyntax ParseLineDirective(SyntaxToken hash, SyntaxToken i
return SyntaxFactory.LineDirectiveTrivia(hash, id, line, file, end, isActive);
}
+ private LineSpanDirectiveTriviaSyntax ParseLineSpanDirective(SyntaxToken hash, SyntaxToken lineKeyword, bool isActive)
+ {
+ Debug.Assert(CurrentToken.Kind == SyntaxKind.OpenParenToken);
+
+ if (isActive)
+ {
+ lineKeyword = CheckFeatureAvailability(lineKeyword, MessageID.IDS_FeatureLineSpanDirective);
+ }
+
+ bool reportError = isActive;
+ var start = ParseLineDirectivePosition(ref reportError, out int startLine, out int startCharacter);
+
+ var minus = EatToken(SyntaxKind.MinusToken, reportError: reportError);
+ if (minus.IsMissing) reportError = false;
+
+ var end = ParseLineDirectivePosition(ref reportError, out int endLine, out int endCharacter);
+ if (reportError &&
+ (endLine < startLine || (endLine == startLine && endCharacter < startCharacter)))
+ {
+ end = this.AddError(end, ErrorCode.ERR_LineSpanDirectiveEndLessThanStart);
+ }
+
+ var characterOffset = (CurrentToken.Kind == SyntaxKind.NumericLiteralToken) ?
+ ParseLineDirectiveNumericLiteral(ref reportError, minValue: 1, maxValue: MaxCharacterValue, out _) :
+ null;
+
+ var file = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.ERR_MissingPPFile, reportError: reportError);
+ if (file.IsMissing) reportError = false;
+
+ var endOfDirective = this.ParseEndOfDirective(ignoreErrors: !reportError);
+ return SyntaxFactory.LineSpanDirectiveTrivia(hash, lineKeyword, start, minus, end, characterOffset, file, endOfDirective, isActive);
+ }
+
+ private LineDirectivePositionSyntax ParseLineDirectivePosition(ref bool reportError, out int line, out int character)
+ {
+ var openParen = EatToken(SyntaxKind.OpenParenToken, reportError);
+ if (openParen.IsMissing) reportError = false;
+
+ var lineToken = ParseLineDirectiveNumericLiteral(ref reportError, minValue: 1, maxValue: MaxLineValue, out line);
+
+ var comma = EatToken(SyntaxKind.CommaToken, reportError);
+ if (comma.IsMissing) reportError = false;
+
+ var characterToken = ParseLineDirectiveNumericLiteral(ref reportError, minValue: 1, maxValue: MaxCharacterValue, out character);
+
+ var closeParen = EatToken(SyntaxKind.CloseParenToken, reportError);
+ if (closeParen.IsMissing) reportError = false;
+
+ return SyntaxFactory.LineDirectivePosition(openParen, lineToken, comma, characterToken, closeParen);
+ }
+
+ private SyntaxToken ParseLineDirectiveNumericLiteral(ref bool reportError, int minValue, int maxValue, out int value)
+ {
+ var token = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.ERR_LineSpanDirectiveInvalidValue, reportError: reportError);
+ value = 0;
+ if (token.IsMissing)
+ {
+ reportError = false;
+ }
+ else if (token.Kind == SyntaxKind.NumericLiteralToken)
+ {
+ value = (int)token.Value;
+ if (value < minValue || value > maxValue)
+ {
+ token = this.AddError(token, ErrorCode.ERR_LineSpanDirectiveInvalidValue);
+ reportError = false;
+ }
+ }
+ return token;
+ }
+
private DirectiveTriviaSyntax ParseReferenceDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool isFollowingToken)
{
if (isActive)
diff --git a/src/Compilers/CSharp/Portable/Parser/Lexer.cs b/src/Compilers/CSharp/Portable/Parser/Lexer.cs
index ea6e89a6cdfb9..42af25f897c20 100644
--- a/src/Compilers/CSharp/Portable/Parser/Lexer.cs
+++ b/src/Compilers/CSharp/Portable/Parser/Lexer.cs
@@ -2836,6 +2836,11 @@ private bool ScanDirectiveToken(ref TokenInfo info)
info.Kind = SyntaxKind.CommaToken;
break;
+ case '-':
+ TextWindow.AdvanceChar();
+ info.Kind = SyntaxKind.MinusToken;
+ break;
+
case '!':
TextWindow.AdvanceChar();
if (TextWindow.PeekChar() == '=')
diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
index 2f2973cf92b42..fbb7cc230cb6e 100644
--- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
@@ -1,5 +1,7 @@
abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax.ColonToken.get -> Microsoft.CodeAnalysis.SyntaxToken
abstract Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax.Expression.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
+abstract Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax.File.get -> Microsoft.CodeAnalysis.SyntaxToken
+abstract Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax.LineKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp10 = 1000 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion
Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax.WithColonToken(Microsoft.CodeAnalysis.SyntaxToken colonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax
@@ -8,17 +10,66 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken colonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.WithColonToken(Microsoft.CodeAnalysis.SyntaxToken colonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.WithExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.Character.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.CloseParenToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.CommaToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.Line.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.OpenParenToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.SyntaxToken line, Microsoft.CodeAnalysis.SyntaxToken commaToken, Microsoft.CodeAnalysis.SyntaxToken character, Microsoft.CodeAnalysis.SyntaxToken closeParenToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.WithCharacter(Microsoft.CodeAnalysis.SyntaxToken character) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.WithCloseParenToken(Microsoft.CodeAnalysis.SyntaxToken closeParenToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.WithCommaToken(Microsoft.CodeAnalysis.SyntaxToken commaToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.WithLine(Microsoft.CodeAnalysis.SyntaxToken line) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.WithOpenParenToken(Microsoft.CodeAnalysis.SyntaxToken openParenToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectiveTriviaSyntax.File.get -> Microsoft.CodeAnalysis.SyntaxToken
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectiveTriviaSyntax.File.get -> Microsoft.CodeAnalysis.SyntaxToken
+*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectiveTriviaSyntax.LineKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectiveTriviaSyntax.LineKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax.WithEndOfDirectiveToken(Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax.WithFile(Microsoft.CodeAnalysis.SyntaxToken file) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax.WithHashToken(Microsoft.CodeAnalysis.SyntaxToken hashToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax.WithLineKeyword(Microsoft.CodeAnalysis.SyntaxToken lineKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineOrSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.CharacterOffset.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.End.get -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.MinusToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.Start.get -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken hashToken, Microsoft.CodeAnalysis.SyntaxToken lineKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax start, Microsoft.CodeAnalysis.SyntaxToken minusToken, Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax end, Microsoft.CodeAnalysis.SyntaxToken characterOffset, Microsoft.CodeAnalysis.SyntaxToken file, Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithCharacterOffset(Microsoft.CodeAnalysis.SyntaxToken characterOffset) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithEnd(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax end) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithEndOfDirectiveToken(Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithFile(Microsoft.CodeAnalysis.SyntaxToken file) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithHashToken(Microsoft.CodeAnalysis.SyntaxToken hashToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithIsActive(bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithLineKeyword(Microsoft.CodeAnalysis.SyntaxToken lineKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithMinusToken(Microsoft.CodeAnalysis.SyntaxToken minusToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.WithStart(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax start) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax.ExpressionColon.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax expressionColon, Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax.WithExpressionColon(Microsoft.CodeAnalysis.CSharp.Syntax.BaseExpressionColonSyntax expressionColon) -> Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax
Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExpressionColon = 9069 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
+Microsoft.CodeAnalysis.CSharp.SyntaxKind.LineDirectivePosition = 9070 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
+Microsoft.CodeAnalysis.CSharp.SyntaxKind.LineSpanDirectiveTrivia = 9071 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.RecordStructDeclaration = 9068 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetUsedAssemblyReferences(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Immutable.ImmutableArray
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionColon(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
+override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitLineDirectivePosition(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
+override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitLineSpanDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
override Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
override Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.ColonToken.get -> Microsoft.CodeAnalysis.SyntaxToken
override Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax.Expression.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.EndOfDirectiveToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.File.get -> Microsoft.CodeAnalysis.SyntaxToken
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.HashToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.IsActive.get -> bool
+override Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax.LineKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
override Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax.Expression.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax.ColonToken.get -> Microsoft.CodeAnalysis.SyntaxToken
override Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax.ColonToken.get -> Microsoft.CodeAnalysis.SyntaxToken
@@ -32,6 +83,11 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Update(
Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ExpressionColon(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression, Microsoft.CodeAnalysis.SyntaxToken colonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LineDirectivePosition(Microsoft.CodeAnalysis.SyntaxToken line, Microsoft.CodeAnalysis.SyntaxToken character) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LineDirectivePosition(Microsoft.CodeAnalysis.SyntaxToken openParenToken, Microsoft.CodeAnalysis.SyntaxToken line, Microsoft.CodeAnalysis.SyntaxToken commaToken, Microsoft.CodeAnalysis.SyntaxToken character, Microsoft.CodeAnalysis.SyntaxToken closeParenToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LineSpanDirectiveTrivia(Microsoft.CodeAnalysis.SyntaxToken hashToken, Microsoft.CodeAnalysis.SyntaxToken lineKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax start, Microsoft.CodeAnalysis.SyntaxToken minusToken, Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax end, Microsoft.CodeAnalysis.SyntaxToken characterOffset, Microsoft.CodeAnalysis.SyntaxToken file, Microsoft.CodeAnalysis.SyntaxToken endOfDirectiveToken, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LineSpanDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax start, Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax end, Microsoft.CodeAnalysis.SyntaxToken characterOffset, Microsoft.CodeAnalysis.SyntaxToken file, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LineSpanDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax start, Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax end, Microsoft.CodeAnalysis.SyntaxToken file, bool isActive) -> Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.WithReturnType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
@@ -55,7 +111,11 @@ Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.GlobalKeyword.get -> M
Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken globalKeyword, Microsoft.CodeAnalysis.SyntaxToken usingKeyword, Microsoft.CodeAnalysis.SyntaxToken staticKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.NameEqualsSyntax alias, Microsoft.CodeAnalysis.CSharp.Syntax.NameSyntax name, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax.WithGlobalKeyword(Microsoft.CodeAnalysis.SyntaxToken globalKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.UsingDirectiveSyntax
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExpressionColon(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax node) -> void
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitLineDirectivePosition(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax node) -> void
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitLineSpanDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitExpressionColon(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionColonSyntax node) -> TResult
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitLineDirectivePosition(Microsoft.CodeAnalysis.CSharp.Syntax.LineDirectivePositionSyntax node) -> TResult
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitLineSpanDirectiveTrivia(Microsoft.CodeAnalysis.CSharp.Syntax.LineSpanDirectiveTriviaSyntax node) -> TResult
*REMOVED*Microsoft.CodeAnalysis.CSharp.SyntaxKind.DataKeyword = 8441 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.GetLineMappings(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Generic.IEnumerable
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.OperatorDeclaration(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifier, Microsoft.CodeAnalysis.SyntaxToken operatorKeyword, Microsoft.CodeAnalysis.SyntaxToken operatorToken, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.OperatorDeclarationSyntax
diff --git a/src/Compilers/CSharp/Portable/Syntax/CSharpLineDirectiveMap.cs b/src/Compilers/CSharp/Portable/Syntax/CSharpLineDirectiveMap.cs
index a254beef31ac5..8fed47ddfd464 100644
--- a/src/Compilers/CSharp/Portable/Syntax/CSharpLineDirectiveMap.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/CSharpLineDirectiveMap.cs
@@ -21,27 +21,34 @@ public CSharpLineDirectiveMap(SyntaxTree syntaxTree)
// Add all active #line directives under trivia into the list, in source code order.
protected override bool ShouldAddDirective(DirectiveTriviaSyntax directive)
{
- return directive.IsActive && directive.Kind() == SyntaxKind.LineDirectiveTrivia;
+ return directive.IsActive && (directive.Kind() is SyntaxKind.LineDirectiveTrivia or SyntaxKind.LineSpanDirectiveTrivia);
}
// Given a directive and the previous entry, create a new entry.
protected override LineMappingEntry GetEntry(DirectiveTriviaSyntax directiveNode, SourceText sourceText, LineMappingEntry previous)
{
Debug.Assert(ShouldAddDirective(directiveNode));
- var directive = (LineDirectiveTriviaSyntax)directiveNode;
// Get line number of NEXT line, hence the +1.
- var directiveLineNumber = sourceText.Lines.IndexOf(directive.SpanStart) + 1;
+ var directiveLineNumber = sourceText.Lines.IndexOf(directiveNode.SpanStart) + 1;
+
+ if (directiveNode is LineSpanDirectiveTriviaSyntax spanDirective)
+ {
+ return GetLineSpanDirectiveEntry(spanDirective, directiveLineNumber);
+ }
+
+ var directive = (LineDirectiveTriviaSyntax)directiveNode;
// The default for the current entry does the same thing as the previous entry, except
// resetting hidden.
var unmappedLine = directiveLineNumber;
- var mappedLine = previous.MappedLine + directiveLineNumber - previous.UnmappedLine;
- var mappedPathOpt = previous.MappedPathOpt;
+ var mappedLine = (previous.State == PositionState.RemappedSpan) ? unmappedLine : previous.MappedLine + directiveLineNumber - previous.UnmappedLine;
+ var mappedPathOpt = (previous.State == PositionState.RemappedSpan) ? null : previous.MappedPathOpt;
PositionState state = PositionState.Unmapped;
// Modify the current entry based on the directive.
SyntaxToken lineToken = directive.Line;
+
if (!lineToken.IsMissing)
{
switch (lineToken.Kind())
@@ -86,6 +93,78 @@ protected override LineMappingEntry GetEntry(DirectiveTriviaSyntax directiveNode
state);
}
+ private static LineMappingEntry GetLineSpanDirectiveEntry(LineSpanDirectiveTriviaSyntax spanDirective, int unmappedLine)
+ {
+ if (!spanDirective.HasErrors &&
+ tryGetPosition(spanDirective.Start, isEnd: false, out LinePosition mappedStart) &&
+ tryGetPosition(spanDirective.End, isEnd: true, out LinePosition mappedEnd) &&
+ tryGetOptionalCharacterOffset(spanDirective.CharacterOffset, out int? characterOffset) &&
+ tryGetStringLiteralValue(spanDirective.File, out string? mappedPathOpt))
+ {
+ return new LineMappingEntry(unmappedLine, new LinePositionSpan(mappedStart, mappedEnd), characterOffset, mappedPathOpt);
+ }
+ return new LineMappingEntry(unmappedLine, unmappedLine, mappedPathOpt: null, PositionState.Unmapped);
+
+ static bool tryGetOneBasedNumericLiteralValue(in SyntaxToken token, out int value)
+ {
+ if (!token.IsMissing &&
+ token.Kind() == SyntaxKind.NumericLiteralToken &&
+ token.Value is int tokenValue)
+ {
+ // convert one-based line number into zero-based line number
+ value = tokenValue - 1;
+ return true;
+ }
+ value = 0;
+ return false;
+ }
+
+ static bool tryGetStringLiteralValue(in SyntaxToken token, out string? value)
+ {
+ if (token.Kind() == SyntaxKind.StringLiteralToken)
+ {
+ value = (string?)token.Value;
+ return true;
+ }
+ value = null;
+ return false;
+ }
+
+ // returns false on error
+ static bool tryGetOptionalCharacterOffset(in SyntaxToken token, out int? value)
+ {
+ if (!token.IsMissing)
+ {
+ if (token.Kind() == SyntaxKind.None)
+ {
+ value = null;
+ return true;
+ }
+ int val = 0;
+ if (tryGetOneBasedNumericLiteralValue(token, out val))
+ {
+ value = val;
+ return true;
+ }
+ }
+ value = null;
+ return false;
+ }
+
+ // returns false on error
+ static bool tryGetPosition(LineDirectivePositionSyntax syntax, bool isEnd, out LinePosition position)
+ {
+ if (tryGetOneBasedNumericLiteralValue(syntax.Line, out int line) &&
+ tryGetOneBasedNumericLiteralValue(syntax.Character, out int character))
+ {
+ position = new LinePosition(line, isEnd ? character + 1 : character);
+ return true;
+ }
+ position = default;
+ return false;
+ }
+ }
+
protected override LineMappingEntry InitializeFirstEntry()
{
// The first entry of the map is always 0,0,null,Unmapped -- the default mapping.
@@ -125,6 +204,7 @@ public override LineVisibility GetLineVisibility(SourceText sourceText, int posi
}
case PositionState.Remapped:
+ case PositionState.RemappedSpan:
return LineVisibility.Visible;
case PositionState.Hidden:
diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
index 19bfc6ccf01aa..b8cabf7960bcb 100644
--- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
+++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
@@ -4735,12 +4735,16 @@
-
+
+
+
+
+
-
+
@@ -4748,7 +4752,49 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
index 5c1e743b646ce..24e70583c7166 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
@@ -859,5 +859,7 @@ public enum SyntaxKind : ushort
RecordStructDeclaration = 9068,
ExpressionColon = 9069,
+ LineDirectivePosition = 9070,
+ LineSpanDirectiveTrivia = 9071,
}
}
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs
index 00c44edd37bc8..9b51d4afad7d7 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKindFacts.cs
@@ -247,6 +247,7 @@ public static bool IsPreprocessorDirective(SyntaxKind kind)
case SyntaxKind.ErrorDirectiveTrivia:
case SyntaxKind.WarningDirectiveTrivia:
case SyntaxKind.LineDirectiveTrivia:
+ case SyntaxKind.LineSpanDirectiveTrivia:
case SyntaxKind.PragmaWarningDirectiveTrivia:
case SyntaxKind.PragmaChecksumDirectiveTrivia:
case SyntaxKind.ReferenceDirectiveTrivia:
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 681d371b2108c..0570a91630e99 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -677,6 +677,16 @@
Metoda {0} s blokem iterátoru musí být asynchronní, aby vrátila {1}.
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Žádná přetížená metoda {0} neodpovídá ukazateli na funkci {1}.
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index ac8302d5b02e1..5efe6c0756cda 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -677,6 +677,16 @@
Die Methode "{0}" mit einem Iteratorblock muss "async" lauten, um "{1}" zurückzugeben.
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Keine Überladung für "{0}" stimmt mit dem Funktionszeiger "{1}" überein.
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 28449569693d6..8fcc19dddb568 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -677,6 +677,16 @@
El método "{0}" con un bloqueo de iterador debe ser "asincrónico" para devolver "{1}"
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Ninguna sobrecarga correspondiente a "{0}" coincide con el puntero de función "{1}".
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 5ae4c587debd5..110006141209d 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -677,6 +677,16 @@
La méthode '{0}' avec un bloc itérateur doit être 'async' pour retourner '{1}'
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Aucune surcharge pour '{0}' ne correspond au pointeur de fonction '{1}'
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 687c587c69e33..2d8aeadcb0b27 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -677,6 +677,16 @@
Il metodo '{0}' con un blocco iteratore deve essere 'async' per restituire '{1}'
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Nessun overload per '{0}' corrisponde al puntatore a funzione '{1}'
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 584fab8afb86f..3c374bd1f9a63 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -677,6 +677,16 @@
反復子ブロックを伴うメソッド '{0}' が '{1}' を返すには 'async' でなければなりません
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
関数ポインター '{1}' に一致する '{0}' のオーバーロードはありません
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index aad215b024ad0..d9f1755292662 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -677,6 +677,16 @@
'{1}'을(를) 반환하려면 반복기 블록이 있는 '{0}' 메서드가 '비동기'여야 합니다.
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
함수 포인터 '{1}'과(와) 일치하는 '{0}'에 대한 오버로드가 없습니다.
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 16e776b6e992f..e50dc5ffa7d45 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -677,6 +677,16 @@
Metoda „{0}” z blokiem iteratora musi być oznaczona jako „async”, aby zwrócić „{1}”
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Żadne z przeciążeń dla elementu „{0}” nie pasuje do wskaźnika funkcji „{1}”
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 8fde0b712cdbf..7733143f14c35 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -677,6 +677,16 @@
O método '{0}' com um bloco do iterador deve ser 'async' para retornar '{1}'
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Nenhuma sobrecarga de '{0}' corresponde ao ponteiro de função '{1}'
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 95c292a3ec8fa..1faec76c91625 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -677,6 +677,16 @@
Чтобы возвращать "{1}", метод "{0}" с блоком итератора должен быть асинхронным ("async").
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
Нет перегруженного метода для "{0}", который соответствует указателю на функцию "{1}".
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index e86a57c511822..df71595d36eea 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -677,6 +677,16 @@
Yineleyici bloku olan '{0}' yönteminin '{1}' döndürmek için 'zaman uyumsuz' olması gerekir
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
'{0}' için aşırı yüklemelerin hiçbiri '{1}' işlev işaretçisiyle eşleşmiyor
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index 150bb0eb61286..bc57dfcd8bcba 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -677,6 +677,16 @@
具有迭代器块的方法“{0}”必须是“异步的”,这样才能返回“{1}”
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
“{0}”没有与函数指针“{1}”匹配的重载
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 4ee731bb84b8a..98acd471b6610 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -677,6 +677,16 @@
具有迭代區塊的方法 '{0}' 必須為「非同步」才能傳回 '{1}'
+
+
+ The #line directive end position must be greater than or equal to the start position
+
+
+
+
+ The #line directive value is missing or out of range
+
+
'{0}' 沒有任何多載符合函式指標 '{1}'
@@ -1137,6 +1147,11 @@
lambda return type
+
+
+ line span directive
+
+
positional fields in records
diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/LineSpanDirectiveTests.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/LineSpanDirectiveTests.cs
new file mode 100644
index 0000000000000..956e37f1f6688
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/LineSpanDirectiveTests.cs
@@ -0,0 +1,593 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Immutable;
+using System.Linq;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.PooledObjects;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.Text;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests
+{
+ public class LineSpanDirectiveTests : CSharpTestBase
+ {
+ [Fact]
+ public void LineSpanDirective_SingleLine()
+ {
+ string sourceA =
+@" A1(); A2(); A3(); //123
+//4567890
+".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"class Program
+{
+ static void Main()
+ {
+#line (1, 16) - (1, 26) 15 ""a.cs""
+ B1(); A2(); A3(); B4();
+ B5();
+ }
+}
+".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "b.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(0,0)-(3,7) -> : (0,0)-(3,7)",
+ "(5,0)-(9,0),14 -> a.cs: (0,15)-(0,26)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"B1();", @"[|A2(); A3();|]"),
+ (@"A2();", @"[|A2(); A3();|]"),
+ (@"A3();", @"[|A3();|]"),
+ (@"B4();", @"[|//123|]"),
+ (@"B5();", @"[|0|]"),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ [Fact]
+ public void LineSpanDirective_MultiLine()
+ {
+ string sourceA =
+@" A1(); A2(); A3(); //123
+//4567890
+//ABCDEF
+".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"class Program
+{
+ static void Main()
+ {
+#line (1, 16) - (5, 26) 15 ""a.cs""
+ B1(); A2(); A3(); B4();
+ B5();
+ }
+}
+".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "b.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(0,0)-(3,7) -> : (0,0)-(3,7)",
+ "(5,0)-(9,0),14 -> a.cs: (0,15)-(4,26)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"B1();", @"[|A2(); A3(); //123
+//4567890
+//ABCDEF
+|]".NormalizeLineEndings()),
+ (@"A2();", @"[|A2(); A3(); //123
+//4567890
+//ABCDEF
+|]".NormalizeLineEndings()),
+ (@"A3();", @"[|A3();|]"),
+ (@"B4();", @"[|//123|]"),
+ (@"B5();", @"[|0|]"),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ [Fact]
+ public void InvalidSpans()
+ {
+ string source =
+@"class Program
+{
+ static void Main()
+ {
+#line (10, 20) - (10, 20) ""A""
+ F();
+#line (10, 20) - (10, 19) ""B""
+ F();
+#line (10, 20) - (9, 20) ""C""
+ F();
+#line (10, 20) - (11, 19) ""D""
+ F();
+ }
+ static void F() { }
+}".NormalizeLineEndings();
+
+ var tree = SyntaxFactory.ParseSyntaxTree(source);
+ var comp = CreateCompilation(tree);
+ comp.VerifyDiagnostics(
+ // (9,18): error CS8939: The #line directive end position must be greater than or equal to the start position
+ // #line (10, 20) - (9, 20) "C"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveEndLessThanStart, "(9, 20)").WithLocation(9, 18),
+ // A(11,18): error CS8939: The #line directive end position must be greater than or equal to the start position
+ // #line (10, 20) - (10, 19) "B"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveEndLessThanStart, "(10, 19)").WithLocation(11, 18));
+
+ var actualLineMappings = GetLineMappings(tree);
+ var expectedLineMappings = new[]
+ {
+ "(0,0)-(3,7) -> : (0,0)-(3,7)",
+ "(5,0)-(5,14) -> A: (9,19)-(9,20)",
+ "(7,0)-(7,14) -> : (7,0)-(7,14)",
+ "(9,0)-(9,14) -> : (9,0)-(9,14)",
+ "(11,0)-(14,1) -> D: (9,19)-(10,19)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+ }
+
+ // 1. First and subsequent spans
+ [WorkItem(4747, "https://github.com/dotnet/csharplang/issues/4747")]
+ [Fact]
+ public void LineSpanDirective_Example1()
+ {
+ string sourceA =
+@" A();B(
+);C();
+ D();
+".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"class Program
+{
+ static void Main() {
+#line (1,10)-(1,15) 3 ""a"" // 3
+ A();B( // 4
+);C(); // 5
+ D(); // 6
+ }
+ static void A() { }
+ static void B() { }
+ static void C() { }
+ static void D() { }
+}".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "b.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(0,0)-(2,23) -> : (0,0)-(2,23)",
+ "(4,0)-(12,1),2 -> a: (0,9)-(0,15)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"A();", @"[|A();B(|]"),
+ (@"B( // 4...", @"[|B(
+);|]".NormalizeLineEndings()),
+ (@"C();", @"[|C();|]"),
+ (@"D();", @"[|D();|]"),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ // 2. Character offset
+ [WorkItem(4747, "https://github.com/dotnet/csharplang/issues/4747")]
+ [Fact]
+ public void LineSpanDirective_Example2()
+ {
+ string sourceA =
+@"@page ""/""
+@F(() => 1+1,
+ () => 2+2
+)".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"#line hidden
+class Page
+{
+void Render()
+{
+#line (2,2)-(4,1) 16 ""page.razor"" // spanof('F(...)')
+ _builder.Add(F(() => 1+1, // 5
+ () => 2+2 // 6
+)); // 7
+#line hidden
+}
+}".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "page.razor.g.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(1,0)-(4,3) -> : (0,0)-(0,0)",
+ "(6,0)-(8,40),15 -> page.razor: (1,1)-(3,1)",
+ "(10,0)-(11,1) -> : (0,0)-(0,0)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var textB = SourceText.From(sourceB);
+ var actualVisibility = textB.Lines.Select(line => treeB.GetLineVisibility(line.Start)).ToImmutableArray();
+ var expectedVisibility = new[]
+ {
+ LineVisibility.BeforeFirstLineDirective,
+ LineVisibility.Hidden,
+ LineVisibility.Hidden,
+ LineVisibility.Hidden,
+ LineVisibility.Hidden,
+ LineVisibility.Hidden,
+ LineVisibility.Visible,
+ LineVisibility.Visible,
+ LineVisibility.Visible,
+ LineVisibility.Visible,
+ LineVisibility.Hidden,
+ LineVisibility.Hidden,
+ };
+ AssertEx.Equal(expectedVisibility, actualVisibility);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"_builder.Add(F(() => 1+1, // 5...", @"[|F(() => 1+1,
+ () => 2+2
+)|]".NormalizeLineEndings()),
+ (@"1+1", @"[|1+1|]"),
+ (@"2+2", @"[|2+2|]"),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ // 3. Razor: Single-line span
+ [WorkItem(4747, "https://github.com/dotnet/csharplang/issues/4747")]
+ [Fact]
+ public void LineSpanDirective_Example3()
+ {
+ string sourceA =
+@"@page ""/""
+Time: @DateTime.Now
+".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"#line hidden
+class Page
+{
+void Render()
+{
+ _builder.Add(""Time:"");
+#line (2,8)-(2,19) 15 ""page.razor"" // spanof('DateTime.Now')
+ _builder.Add(DateTime.Now);
+#line hidden
+}
+}".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "page.razor.g.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(1,0)-(5,26) -> : (0,0)-(0,0)",
+ "(7,0)-(7,31),14 -> page.razor: (1,7)-(1,19)",
+ "(9,0)-(10,1) -> : (0,0)-(0,0)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"_builder.Add(""Time:"");", @"[||]"),
+ (@"_builder.Add(DateTime.Now);", @"[|DateTime.Now|]"),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ // 4. Razor: Multi-line span
+ [WorkItem(4747, "https://github.com/dotnet/csharplang/issues/4747")]
+ [Fact]
+ public void LineSpanDirective_Example4()
+ {
+ string sourceA =
+@"@page ""/""
+@JsonToHtml(@""
+{
+ """"key1"""": """"value1"""",
+ """"key2"""": """"value2""""
+}"")".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"#line hidden
+class Page
+{
+void Render()
+{
+#line (2,2)-(6,3) 16 ""page.razor"" // spanof('JsonToHtml(...)')
+ _builder.Add(JsonToHtml(@""
+{
+ """"key1"""": """"value1"""",
+ """"key2"""": """"value2""""
+}""));
+#line hidden
+}
+}".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "page.razor.g.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(1,0)-(4,3) -> : (0,0)-(0,0)",
+ "(6,0)-(10,7),15 -> page.razor: (1,1)-(5,3)",
+ "(12,0)-(13,1) -> : (0,0)-(0,0)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"_builder.Add(JsonToHtml(@""...", @"[|JsonToHtml(@""
+{
+ """"key1"""": """"value1"""",
+ """"key2"""": """"value2""""
+}"")|]".NormalizeLineEndings()),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ // 5i. Razor: block constructs
+ [WorkItem(4747, "https://github.com/dotnet/csharplang/issues/4747")]
+ [Fact]
+ public void LineSpanDirective_Example5i()
+ {
+ string sourceA =
+@"@Html.Helper(() =>
+{
+ Hello World
+ @DateTime.Now
+})".NormalizeLineEndings();
+ var textA = SourceText.From(sourceA);
+
+ string sourceB =
+@"using System;
+class Page
+{
+ Builder _builder;
+ void Execute()
+ {
+#line (1, 2) - (5, 2) 22 ""a.razor"" // spanof('HtmlHelper(() => { ... })')
+ _builder.Add(Html.Helper(() =>
+#line 2 ""a.razor"" // lineof('{')
+ {
+#line (4, 6) - (4, 17) 26 ""a.razor"" // spanof('DateTime.Now')
+ _builder.Add(DateTime.Now);
+#line 5 ""a.razor"" // lineof('})')
+ })
+#line hidden
+ );
+ }
+}".NormalizeLineEndings();
+
+ var treeB = SyntaxFactory.ParseSyntaxTree(sourceB, path: "a.razor.g.cs");
+ treeB.GetDiagnostics().Verify();
+
+ var actualLineMappings = GetLineMappings(treeB);
+ var expectedLineMappings = new[]
+ {
+ "(0,0)-(5,7) -> : (0,0)-(5,7)",
+ "(7,0)-(7,40),21 -> a.razor: (0,1)-(4,2)",
+ "(9,0)-(9,11) -> a.razor: (1,0)-(1,11)",
+ "(11,0)-(11,41),25 -> a.razor: (3,5)-(3,17)",
+ "(13,0)-(13,12) -> a.razor: (4,0)-(4,12)",
+ "(15,0)-(17,1) -> : (0,0)-(0,0)",
+ };
+ AssertEx.Equal(expectedLineMappings, actualLineMappings);
+
+ var statements = GetStatementsAndExpressionBodies(treeB);
+ var actualTextSpans = statements.SelectAsArray(s => GetTextMapping(textA, treeB, s));
+ var expectedTextSpans = new[]
+ {
+ (@"_builder.Add(Html.Helper(() =>...", @"[|Html.Helper(() =>
+{
+ Hello World
+ @DateTime.Now
+})|]".NormalizeLineEndings()),
+ (@"_builder.Add(DateTime.Now);", @"[|DateTime.Now|]"),
+ };
+ AssertEx.Equal(expectedTextSpans, actualTextSpans);
+ }
+
+ private static ImmutableArray GetStatementsAndExpressionBodies(SyntaxTree tree)
+ {
+ var builder = ArrayBuilder.GetInstance();
+ foreach (var syntax in tree.GetRoot().DescendantNodesAndSelf())
+ {
+ switch (syntax)
+ {
+ case ExpressionStatementSyntax:
+ builder.Add(syntax);
+ break;
+ case ParenthesizedLambdaExpressionSyntax lambda:
+ builder.AddIfNotNull(lambda.ExpressionBody);
+ break;
+ case SimpleLambdaExpressionSyntax lambda:
+ builder.AddIfNotNull(lambda.ExpressionBody);
+ break;
+ }
+ }
+ return builder.ToImmutableAndFree();
+ }
+
+ private static ImmutableArray GetLineMappings(SyntaxTree tree)
+ {
+ return tree.GetLineMappings().Select(mapping => mapping.ToString()!).ToImmutableArray();
+ }
+
+ private static (string, string) GetTextMapping(SourceText mappedText, SyntaxTree unmappedText, SyntaxNode syntax)
+ {
+ return (getDescription(syntax), getMapping(mappedText, unmappedText, syntax));
+
+ static string getDescription(SyntaxNode syntax)
+ {
+ var description = syntax.ToString();
+ int index = description.IndexOfAny(new[] { '\r', '\n' });
+ return index < 0 ?
+ description :
+ description.Substring(0, index) + "...";
+ }
+
+ static string getMapping(SourceText mappedText, SyntaxTree unmappedText, SyntaxNode syntax)
+ {
+ var mappedLineAndPositionSpan = unmappedText.GetMappedLineSpanAndVisibility(syntax.Span, out _);
+ var span = getTextSpan(mappedText.Lines, mappedLineAndPositionSpan.Span);
+ return $"[|{mappedText.GetSubText(span)}|]";
+ }
+
+ static TextSpan getTextSpan(TextLineCollection lines, LinePositionSpan span)
+ {
+ return TextSpan.FromBounds(getTextPosition(lines, span.Start), getTextPosition(lines, span.End));
+ }
+
+ static int getTextPosition(TextLineCollection lines, LinePosition position)
+ {
+ if (position.Line < lines.Count)
+ {
+ var line = lines[position.Line];
+ return Math.Min(line.Start + position.Character, line.End);
+ }
+ return (lines.Count == 0) ? 0 : lines[^1].End;
+ }
+ }
+
+ [Fact]
+ public void Diagnostics()
+ {
+ var source =
+@"class Program
+{
+ static void Main()
+ {
+#line (3, 3) - (6, 6) 8 ""a.txt""
+ A();
+#line default
+ B();
+#line (1, 1) - (1, 100) ""b.txt""
+ C();
+ }
+}".NormalizeLineEndings();
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // b.txt(1,9): error CS0103: The name 'C' does not exist in the current context
+ // C();
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "C").WithArguments("C").WithLocation(1, 9),
+ // a.txt(3,4): error CS0103: The name 'A' does not exist in the current context
+ // A();
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "A").WithArguments("A").WithLocation(3, 4),
+ // (8,9): error CS0103: The name 'B' does not exist in the current context
+ // B();
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "B").WithArguments("B").WithLocation(8, 9));
+ }
+
+ [Fact]
+ public void SequencePoints()
+ {
+ var source =
+@"class Program
+{
+ static void Main()
+ {
+#line (3, 3) - (6, 6) 8 ""a.txt""
+ A();
+#line default
+ B();
+#line (1, 1) - (1, 100) ""b.txt""
+ C();
+ }
+ static void A() { }
+ static void B() { }
+ static void C() { }
+}".NormalizeLineEndings();
+ var verifier = CompileAndVerify(source, options: TestOptions.DebugDll);
+ verifier.VerifyIL("Program.Main", sequencePoints: "Program.Main", expectedIL:
+@"{
+ // Code size 20 (0x14)
+ .maxstack 0
+ -IL_0000: nop
+ -IL_0001: call ""void Program.A()""
+ IL_0006: nop
+ -IL_0007: call ""void Program.B()""
+ IL_000c: nop
+ -IL_000d: call ""void Program.C()""
+ IL_0012: nop
+ -IL_0013: ret
+}");
+ verifier.VerifyPdb("Program.Main", expectedPdb:
+@"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+");
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
index 7518250d755d0..b480da073976c 100644
--- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
@@ -688,6 +688,12 @@ private static Syntax.InternalSyntax.UndefDirectiveTriviaSyntax GenerateUndefDir
private static Syntax.InternalSyntax.LineDirectiveTriviaSyntax GenerateLineDirectiveTrivia()
=> InternalSyntaxFactory.LineDirectiveTrivia(InternalSyntaxFactory.Token(SyntaxKind.HashToken), InternalSyntaxFactory.Token(SyntaxKind.LineKeyword), InternalSyntaxFactory.Literal(null, "1", 1, null), null, InternalSyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), new bool());
+ private static Syntax.InternalSyntax.LineDirectivePositionSyntax GenerateLineDirectivePosition()
+ => InternalSyntaxFactory.LineDirectivePosition(InternalSyntaxFactory.Token(SyntaxKind.OpenParenToken), InternalSyntaxFactory.Literal(null, "1", 1, null), InternalSyntaxFactory.Token(SyntaxKind.CommaToken), InternalSyntaxFactory.Literal(null, "1", 1, null), InternalSyntaxFactory.Token(SyntaxKind.CloseParenToken));
+
+ private static Syntax.InternalSyntax.LineSpanDirectiveTriviaSyntax GenerateLineSpanDirectiveTrivia()
+ => InternalSyntaxFactory.LineSpanDirectiveTrivia(InternalSyntaxFactory.Token(SyntaxKind.HashToken), InternalSyntaxFactory.Token(SyntaxKind.LineKeyword), GenerateLineDirectivePosition(), InternalSyntaxFactory.Token(SyntaxKind.MinusToken), GenerateLineDirectivePosition(), null, InternalSyntaxFactory.Literal(null, "string", "string", null), InternalSyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), new bool());
+
private static Syntax.InternalSyntax.PragmaWarningDirectiveTriviaSyntax GeneratePragmaWarningDirectiveTrivia()
=> InternalSyntaxFactory.PragmaWarningDirectiveTrivia(InternalSyntaxFactory.Token(SyntaxKind.HashToken), InternalSyntaxFactory.Token(SyntaxKind.PragmaKeyword), InternalSyntaxFactory.Token(SyntaxKind.WarningKeyword), InternalSyntaxFactory.Token(SyntaxKind.DisableKeyword), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), new bool());
@@ -3592,6 +3598,38 @@ public void TestLineDirectiveTriviaFactoryAndProperties()
AttachAndCheckDiagnostics(node);
}
+ [Fact]
+ public void TestLineDirectivePositionFactoryAndProperties()
+ {
+ var node = GenerateLineDirectivePosition();
+
+ Assert.Equal(SyntaxKind.OpenParenToken, node.OpenParenToken.Kind);
+ Assert.Equal(SyntaxKind.NumericLiteralToken, node.Line.Kind);
+ Assert.Equal(SyntaxKind.CommaToken, node.CommaToken.Kind);
+ Assert.Equal(SyntaxKind.NumericLiteralToken, node.Character.Kind);
+ Assert.Equal(SyntaxKind.CloseParenToken, node.CloseParenToken.Kind);
+
+ AttachAndCheckDiagnostics(node);
+ }
+
+ [Fact]
+ public void TestLineSpanDirectiveTriviaFactoryAndProperties()
+ {
+ var node = GenerateLineSpanDirectiveTrivia();
+
+ Assert.Equal(SyntaxKind.HashToken, node.HashToken.Kind);
+ Assert.Equal(SyntaxKind.LineKeyword, node.LineKeyword.Kind);
+ Assert.NotNull(node.Start);
+ Assert.Equal(SyntaxKind.MinusToken, node.MinusToken.Kind);
+ Assert.NotNull(node.End);
+ Assert.Null(node.CharacterOffset);
+ Assert.Equal(SyntaxKind.StringLiteralToken, node.File.Kind);
+ Assert.Equal(SyntaxKind.EndOfDirectiveToken, node.EndOfDirectiveToken.Kind);
+ Assert.Equal(new bool(), node.IsActive);
+
+ AttachAndCheckDiagnostics(node);
+ }
+
[Fact]
public void TestPragmaWarningDirectiveTriviaFactoryAndProperties()
{
@@ -9559,6 +9597,58 @@ public void TestLineDirectiveTriviaIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestLineDirectivePositionTokenDeleteRewriter()
+ {
+ var oldNode = GenerateLineDirectivePosition();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestLineDirectivePositionIdentityRewriter()
+ {
+ var oldNode = GenerateLineDirectivePosition();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
+ [Fact]
+ public void TestLineSpanDirectiveTriviaTokenDeleteRewriter()
+ {
+ var oldNode = GenerateLineSpanDirectiveTrivia();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestLineSpanDirectiveTriviaIdentityRewriter()
+ {
+ var oldNode = GenerateLineSpanDirectiveTrivia();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestPragmaWarningDirectiveTriviaTokenDeleteRewriter()
{
@@ -10398,6 +10488,12 @@ private static UndefDirectiveTriviaSyntax GenerateUndefDirectiveTrivia()
private static LineDirectiveTriviaSyntax GenerateLineDirectiveTrivia()
=> SyntaxFactory.LineDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.LineKeyword), SyntaxFactory.Literal("1", 1), default(SyntaxToken), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), new bool());
+ private static LineDirectivePositionSyntax GenerateLineDirectivePosition()
+ => SyntaxFactory.LineDirectivePosition(SyntaxFactory.Token(SyntaxKind.OpenParenToken), SyntaxFactory.Literal("1", 1), SyntaxFactory.Token(SyntaxKind.CommaToken), SyntaxFactory.Literal("1", 1), SyntaxFactory.Token(SyntaxKind.CloseParenToken));
+
+ private static LineSpanDirectiveTriviaSyntax GenerateLineSpanDirectiveTrivia()
+ => SyntaxFactory.LineSpanDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.LineKeyword), GenerateLineDirectivePosition(), SyntaxFactory.Token(SyntaxKind.MinusToken), GenerateLineDirectivePosition(), default(SyntaxToken), SyntaxFactory.Literal("string", "string"), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), new bool());
+
private static PragmaWarningDirectiveTriviaSyntax GeneratePragmaWarningDirectiveTrivia()
=> SyntaxFactory.PragmaWarningDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.HashToken), SyntaxFactory.Token(SyntaxKind.PragmaKeyword), SyntaxFactory.Token(SyntaxKind.WarningKeyword), SyntaxFactory.Token(SyntaxKind.DisableKeyword), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken), new bool());
@@ -13302,6 +13398,38 @@ public void TestLineDirectiveTriviaFactoryAndProperties()
Assert.Equal(node, newNode);
}
+ [Fact]
+ public void TestLineDirectivePositionFactoryAndProperties()
+ {
+ var node = GenerateLineDirectivePosition();
+
+ Assert.Equal(SyntaxKind.OpenParenToken, node.OpenParenToken.Kind());
+ Assert.Equal(SyntaxKind.NumericLiteralToken, node.Line.Kind());
+ Assert.Equal(SyntaxKind.CommaToken, node.CommaToken.Kind());
+ Assert.Equal(SyntaxKind.NumericLiteralToken, node.Character.Kind());
+ Assert.Equal(SyntaxKind.CloseParenToken, node.CloseParenToken.Kind());
+ var newNode = node.WithOpenParenToken(node.OpenParenToken).WithLine(node.Line).WithCommaToken(node.CommaToken).WithCharacter(node.Character).WithCloseParenToken(node.CloseParenToken);
+ Assert.Equal(node, newNode);
+ }
+
+ [Fact]
+ public void TestLineSpanDirectiveTriviaFactoryAndProperties()
+ {
+ var node = GenerateLineSpanDirectiveTrivia();
+
+ Assert.Equal(SyntaxKind.HashToken, node.HashToken.Kind());
+ Assert.Equal(SyntaxKind.LineKeyword, node.LineKeyword.Kind());
+ Assert.NotNull(node.Start);
+ Assert.Equal(SyntaxKind.MinusToken, node.MinusToken.Kind());
+ Assert.NotNull(node.End);
+ Assert.Equal(SyntaxKind.None, node.CharacterOffset.Kind());
+ Assert.Equal(SyntaxKind.StringLiteralToken, node.File.Kind());
+ Assert.Equal(SyntaxKind.EndOfDirectiveToken, node.EndOfDirectiveToken.Kind());
+ Assert.Equal(new bool(), node.IsActive);
+ var newNode = node.WithHashToken(node.HashToken).WithLineKeyword(node.LineKeyword).WithStart(node.Start).WithMinusToken(node.MinusToken).WithEnd(node.End).WithCharacterOffset(node.CharacterOffset).WithFile(node.File).WithEndOfDirectiveToken(node.EndOfDirectiveToken).WithIsActive(node.IsActive);
+ Assert.Equal(node, newNode);
+ }
+
[Fact]
public void TestPragmaWarningDirectiveTriviaFactoryAndProperties()
{
@@ -19269,6 +19397,58 @@ public void TestLineDirectiveTriviaIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestLineDirectivePositionTokenDeleteRewriter()
+ {
+ var oldNode = GenerateLineDirectivePosition();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestLineDirectivePositionIdentityRewriter()
+ {
+ var oldNode = GenerateLineDirectivePosition();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
+ [Fact]
+ public void TestLineSpanDirectiveTriviaTokenDeleteRewriter()
+ {
+ var oldNode = GenerateLineSpanDirectiveTrivia();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestLineSpanDirectiveTriviaIdentityRewriter()
+ {
+ var oldNode = GenerateLineSpanDirectiveTrivia();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestPragmaWarningDirectiveTriviaTokenDeleteRewriter()
{
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LineSpanDirectiveParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LineSpanDirectiveParsingTests.cs
new file mode 100644
index 0000000000000..6228c010f379d
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LineSpanDirectiveParsingTests.cs
@@ -0,0 +1,1833 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests
+{
+ public class LineSpanDirectiveParsingTests : ParsingTests
+ {
+ public LineSpanDirectiveParsingTests(ITestOutputHelper output) : base(output) { }
+
+ protected override SyntaxTree ParseTree(string text, CSharpParseOptions? options)
+ {
+ return SyntaxFactory.ParseSyntaxTree(text, options: options);
+ }
+
+ protected override CSharpSyntaxNode ParseNode(string text, CSharpParseOptions? options)
+ {
+ return SyntaxFactory.ParseExpression(text, options: options);
+ }
+
+ private void UsingLineDirective(string text, CSharpParseOptions? options, params DiagnosticDescription[] expectedErrors)
+ {
+ var node = ParseTree(text, options).GetCompilationUnitRoot();
+ Validate(text, node, expectedErrors);
+ UsingNode(node.GetDirectives().Single(d => d.Kind() is SyntaxKind.LineDirectiveTrivia or SyntaxKind.LineSpanDirectiveTrivia));
+ }
+
+ [Fact]
+ public void IsActive()
+ {
+ string source =
+@"#if IsActive
+#line (1, 2) - (3, 4) ""file.cs""
+#endif";
+
+ UsingLineDirective(source, TestOptions.Regular9);
+ verify();
+
+ UsingLineDirective(source, TestOptions.Regular9.WithPreprocessorSymbols("IsActive"),
+ // (2,2): error CS8773: Feature 'line span directive' is not available in C# 9.0. Please use language version 10.0 or greater.
+ // #line (1, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "line").WithArguments("line span directive", "10.0").WithLocation(2, 2));
+ verify();
+
+ void verify()
+ {
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+ }
+
+ [Fact]
+ public void LineDirective_01()
+ {
+ string source = @"#line (1, 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, TestOptions.Regular9,
+ // (1,2): error CS8773: Feature 'line span directive' is not available in C# 9.0. Please use language version 10.0 or greater.
+ // #line (1, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "line").WithArguments("line span directive", "10.0").WithLocation(1, 2));
+ verify();
+
+ UsingLineDirective(source, TestOptions.Regular10);
+ verify();
+
+ void verify()
+ {
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+ }
+
+ [Fact]
+ public void LineDirective_02()
+ {
+ string source = @"#line (1, 2) - (3, 4) 5 ""file.cs""";
+
+ UsingLineDirective(source, TestOptions.Regular9,
+ // (1,2): error CS8773: Feature 'line span directive' is not available in C# 9.0. Please use language version 10.0 or greater.
+ // #line (1, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "line").WithArguments("line span directive", "10.0").WithLocation(1, 2));
+ verify();
+
+ UsingLineDirective(source, TestOptions.Regular10);
+ verify();
+
+ void verify()
+ {
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "5");
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+ }
+
+ [Fact]
+ public void LineDirective_03()
+ {
+ string source = @"#line (1, 2) - (3, 4) """"";
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void LineDirective_04()
+ {
+ string source = @" # line ( 1 , 2 ) - ( 3 , 4 ) 5 "" """;
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "5");
+ N(SyntaxKind.StringLiteralToken, "\" \"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void LineDirective_05()
+ {
+ string source = @"#line(1,2)-(3,4)""file.cs""";
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void LineDirective_06()
+ {
+ string source = @"#line(1,2)-(3,4)5""file.cs""";
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "5");
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_01()
+ {
+ string source = @"#line (";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line (
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "").WithLocation(1, 8));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_02()
+ {
+ string source = @"#line (1";
+
+ UsingLineDirective(source, options: null,
+ // (1,9): error CS1003: Syntax error, ',' expected
+ // #line (1
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(",", "").WithLocation(1, 9));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_03()
+ {
+ string source = @"#line (1,";
+
+ UsingLineDirective(source, options: null,
+ // (1,10): error CS8938: The #line directive value is missing or out of range
+ // #line (1,
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "").WithLocation(1, 10));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_04()
+ {
+ string source = @"#line (1, 2";
+
+ UsingLineDirective(source, options: null,
+ // (1,12): error CS1026: ) expected
+ // #line (1, 2
+ Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 12));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_05()
+ {
+ string source = @"#line (1, 2)";
+
+ UsingLineDirective(source, options: null,
+ // (1,13): error CS1003: Syntax error, '-' expected
+ // #line (1, 2)
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("-", "").WithLocation(1, 13));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_06()
+ {
+ string source = @"#line (1, 2) -";
+
+ UsingLineDirective(source, options: null,
+ // (1,15): error CS1003: Syntax error, '(' expected
+ // #line (1, 2) -
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("(", "").WithLocation(1, 15));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_07()
+ {
+ string source = @"#line (1, 2) - (";
+
+ UsingLineDirective(source, options: null,
+ // (1,17): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "").WithLocation(1, 17));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_08()
+ {
+ string source = @"#line (1, 2) - (3";
+
+ UsingLineDirective(source, options: null,
+ // (1,18): error CS1003: Syntax error, ',' expected
+ // #line (1, 2) - (3
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(",", "").WithLocation(1, 18));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_09()
+ {
+ string source = @"#line (1, 2) - (3,";
+
+ UsingLineDirective(source, options: null,
+ // (1,19): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (3,
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "").WithLocation(1, 19));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_10()
+ {
+ string source = @"#line (1, 2) - (3, 4";
+
+ UsingLineDirective(source, options: null,
+ // (1,21): error CS1026: ) expected
+ // #line (1, 2) - (3, 4
+ Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 21));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_11()
+ {
+ string source = @"#line (1, 2) - (3, 4)";
+
+ UsingLineDirective(source, options: null,
+ // (1,22): error CS1578: Quoted file name, single-line comment or end-of-line expected
+ // #line (1, 2) - (3, 4)
+ Diagnostic(ErrorCode.ERR_MissingPPFile, "").WithLocation(1, 22));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_12()
+ {
+ string source = @"#line (1, 2) - (3, 4) 5";
+
+ UsingLineDirective(source, options: null,
+ // (1,24): error CS1578: Quoted file name, single-line comment or end-of-line expected
+ // #line (1, 2) - (3, 4) 5
+ Diagnostic(ErrorCode.ERR_MissingPPFile, "").WithLocation(1, 24));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "5");
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Incomplete_13()
+ {
+ ParseIncompleteSyntax(@"#line (1, 2) - (3, 4) 5 ""file.cs""");
+ }
+
+ [Fact]
+ public void Missing_01()
+ {
+ string source = @"#line 1, 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS1578: Quoted file name, single-line comment or end-of-line expected
+ // #line 1, 2) - 3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_MissingPPFile, ",").WithLocation(1, 8));
+
+ N(SyntaxKind.LineDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_02()
+ {
+ string source = @"#line (, 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line (, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, ",").WithLocation(1, 8));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_03()
+ {
+ string source = @"#line (1 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,10): error CS1003: Syntax error, ',' expected
+ // #line (1 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_SyntaxError, "2").WithArguments(",", "").WithLocation(1, 10));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_04()
+ {
+ string source = @"#line (1, ) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,11): error CS8938: The #line directive value is missing or out of range
+ // #line (1, ) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, ")").WithLocation(1, 11));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_05()
+ {
+ string source = @"#line (1, 2 - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,13): error CS1026: ) expected
+ // #line (1, 2 - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_CloseParenExpected, "-").WithLocation(1, 13));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ M(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_06()
+ {
+ string source = @"#line (1, 2) (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,14): error CS1003: Syntax error, '-' expected
+ // #line (1, 2) (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("-", "(").WithLocation(1, 14));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_07()
+ {
+ string source = @"#line (1, 2) - 3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,16): error CS1003: Syntax error, '(' expected
+ // #line (1, 2) - 3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_SyntaxError, "3").WithArguments("(", "").WithLocation(1, 16));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_08()
+ {
+ string source = @"#line (1, 2) - (, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,17): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, ",").WithLocation(1, 17));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_09()
+ {
+ string source = @"#line (1, 2) - (3 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,19): error CS1003: Syntax error, ',' expected
+ // #line (1, 2) - (3 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_SyntaxError, "4").WithArguments(",", "").WithLocation(1, 19));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_10()
+ {
+ string source = @"#line (1, 2) - (3, ) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,20): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (3, ) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, ")").WithLocation(1, 20));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Missing_11()
+ {
+ string source = @"#line (1, 2) - (3, 4 ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,22): error CS1026: ) expected
+ // #line (1, 2) - (3, 4 "file.cs"
+ Diagnostic(ErrorCode.ERR_CloseParenExpected, @"""file.cs""").WithLocation(1, 22));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ M(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_01()
+ {
+ string source = @"#line ('1', 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line ('1', 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "'").WithLocation(1, 8));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_02()
+ {
+ string source = @"#line (1, ""2"") - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,11): error CS8938: The #line directive value is missing or out of range
+ // #line (1, "2") - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, @"""2""").WithLocation(1, 11));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"2\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_03()
+ {
+ string source = @"#line (1, 2) - (0b11, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,17): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (0b11, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 17));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "0");
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_04()
+ {
+ string source = @"#line (1, 2) - (3, 0x04) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,20): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (3, 0x04) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 20));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "0");
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_05()
+ {
+ string source = @"#line (null, 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line (null, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "null").WithLocation(1, 8));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_06()
+ {
+ string source = @"#line (1, true) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,11): error CS8938: The #line directive value is missing or out of range
+ // #line (1, true) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "true").WithLocation(1, 11));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_07()
+ {
+ string source = @"#line (1, 2) - (int, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,17): error CS8938: The #line directive value is missing or out of range
+ // #line (1, 2) - (int, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "int").WithLocation(1, 17));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_08()
+ {
+ string source = @"#line (1u, 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,9): error CS1003: Syntax error, ',' expected
+ // #line (1u, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_SyntaxError, "u").WithArguments(",", "").WithLocation(1, 9));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_09()
+ {
+ string source = @"#line (1, 2f) - (3, 4) "" """;
+
+ UsingLineDirective(source, options: null,
+ // (1,12): error CS1026: ) expected
+ // #line (1, 2f) - (3, 4) " "
+ Diagnostic(ErrorCode.ERR_CloseParenExpected, "f").WithLocation(1, 12));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.MinusToken);
+ M(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UnexpectedToken_11()
+ {
+ string source = @"#line (1, 2) - (3, 4) file.cs";
+
+ UsingLineDirective(source, options: null,
+ // (1,23): error CS1578: Quoted file name, single-line comment or end-of-line expected
+ // #line (1, 2) - (3, 4) file.cs
+ Diagnostic(ErrorCode.ERR_MissingPPFile, "file").WithLocation(1, 23));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "3");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "4");
+ N(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifyValue_01()
+ {
+ string source = @"#line (-1, 2) - (3, 4) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line (-1, 2) - (3, 4) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "-").WithLocation(1, 8));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CommaToken);
+ M(SyntaxKind.NumericLiteralToken);
+ M(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ M(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "2");
+ N(SyntaxKind.CloseParenToken);
+ }
+ M(SyntaxKind.StringLiteralToken);
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifyValue_02()
+ {
+ string source = @"#line (0, 0) - (0, 0) 0 ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line (0, 0) - (0, 0) 0 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 8),
+ // (1,11): error CS8938: The #line directive value is missing or out of range
+ // #line (0, 0) - (0, 0) 0 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 11),
+ // (1,17): error CS8938: The #line directive value is missing or out of range
+ // #line (0, 0) - (0, 0) 0 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 17),
+ // (1,20): error CS8938: The #line directive value is missing or out of range
+ // #line (0, 0) - (0, 0) 0 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 20),
+ // (1,23): error CS8938: The #line directive value is missing or out of range
+ // #line (0, 0) - (0, 0) 0 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "0").WithLocation(1, 23));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "0");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "0");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "0");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "0");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "0");
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifyValue_03()
+ {
+ string source = @"#line (16707565, 65536) - (16707565, 65536) 65536 ""file.cs""";
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "16707565");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "65536");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "16707565");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "65536");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "65536");
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifyValue_04()
+ {
+ string source = @"#line (16707566, 65537) - (16707566, 65537) 65537 ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,8): error CS8938: The #line directive value is missing or out of range
+ // #line (16707566, 65537) - (16707566, 65537) 65537 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "16707566").WithLocation(1, 8),
+ // (1,18): error CS8938: The #line directive value is missing or out of range
+ // #line (16707566, 65537) - (16707566, 65537) 65537 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "65537").WithLocation(1, 18),
+ // (1,28): error CS8938: The #line directive value is missing or out of range
+ // #line (16707566, 65537) - (16707566, 65537) 65537 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "16707566").WithLocation(1, 28),
+ // (1,38): error CS8938: The #line directive value is missing or out of range
+ // #line (16707566, 65537) - (16707566, 65537) 65537 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "65537").WithLocation(1, 38),
+ // (1,45): error CS8938: The #line directive value is missing or out of range
+ // #line (16707566, 65537) - (16707566, 65537) 65537 "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveInvalidValue, "65537").WithLocation(1, 45));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "16707566");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "65537");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "16707566");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "65537");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.NumericLiteralToken, "65537");
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifySpan_01()
+ {
+ string source = @"#line (10, 20) - (10, 20) ""file.cs""";
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "10");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "20");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "10");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "20");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifySpan_02()
+ {
+ string source = @"#line (10, 20) - (10, 19) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,18): error CS8939: The #line directive end position must be greater than or equal to the start position
+ // #line (10, 20) - (10, 19) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveEndLessThanStart, "(10, 19)").WithLocation(1, 18));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "10");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "20");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "10");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "19");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifySpan_03()
+ {
+ string source = @"#line (10, 20) - (9, 20) ""file.cs""";
+
+ UsingLineDirective(source, options: null,
+ // (1,18): error CS8939: The #line directive end position must be greater than or equal to the start position
+ // #line (10, 20) - (9, 20) "file.cs"
+ Diagnostic(ErrorCode.ERR_LineSpanDirectiveEndLessThanStart, "(9, 20)").WithLocation(1, 18));
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "10");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "20");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "9");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "20");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VerifySpan_04()
+ {
+ string source = @"#line (10, 20) - (11, 1) ""file.cs""";
+
+ UsingLineDirective(source, options: null);
+
+ N(SyntaxKind.LineSpanDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.LineKeyword);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "10");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "20");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.MinusToken);
+ N(SyntaxKind.LineDirectivePosition);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.NumericLiteralToken, "11");
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.NumericLiteralToken, "1");
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.StringLiteralToken, "\"file.cs\"");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ EOF();
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs
index 8f430d1182bfc..17f180d628916 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingTests.cs
@@ -93,10 +93,7 @@ internal void UsingStatement(string text, params DiagnosticDescription[] expecte
internal void UsingStatement(string text, ParseOptions? options, params DiagnosticDescription[] expectedErrors)
{
var node = SyntaxFactory.ParseStatement(text, options: options);
- // we validate the text roundtrips
- Assert.Equal(text, node.ToFullString());
- var actualErrors = node.GetDiagnostics();
- actualErrors.Verify(expectedErrors);
+ Validate(text, node, expectedErrors);
UsingNode(node);
}
@@ -126,12 +123,17 @@ internal void UsingExpression(string text, ParseOptions? options, params Diagnos
}
protected void UsingNode(string text, CSharpSyntaxNode node, DiagnosticDescription[] expectedErrors)
+ {
+ Validate(text, node, expectedErrors);
+ UsingNode(node);
+ }
+
+ protected void Validate(string text, CSharpSyntaxNode node, params DiagnosticDescription[] expectedErrors)
{
// we validate the text roundtrips
Assert.Equal(text, node.ToFullString());
var actualErrors = node.GetDiagnostics();
actualErrors.Verify(expectedErrors);
- UsingNode(node);
}
internal void UsingExpression(string text, params DiagnosticDescription[] expectedErrors)
@@ -190,15 +192,17 @@ protected SyntaxNodeOrToken N(SyntaxKind kind, string? value = null)
try
{
Assert.True(_treeEnumerator!.MoveNext());
- Assert.Equal(kind, _treeEnumerator.Current.Kind());
- Assert.False(_treeEnumerator.Current.IsMissing);
+ var current = _treeEnumerator.Current;
+
+ Assert.Equal(kind, current.Kind());
+ Assert.False(current.IsMissing);
if (value != null)
{
- Assert.Equal(_treeEnumerator.Current.ToString(), value);
+ Assert.Equal(current.ToString(), value);
}
- return _treeEnumerator.Current;
+ return current;
}
catch when (DumpAndCleanup())
{
@@ -286,11 +290,13 @@ private void Print(SyntaxNodeOrToken node, bool dump)
{
case SyntaxKind.IdentifierToken:
case SyntaxKind.NumericLiteralToken:
+ case SyntaxKind.StringLiteralToken:
if (node.IsMissing)
{
goto default;
}
- _output.WriteLine(@"N(SyntaxKind.{0}, ""{1}"");", node.Kind(), node.ToString());
+ var value = node.ToString().Replace("\"", "\\\"");
+ _output.WriteLine(@"N(SyntaxKind.{0}, ""{1}"");", node.Kind(), value);
break;
default:
_output.WriteLine("{0}(SyntaxKind.{1});", node.IsMissing ? "M" : "N", node.Kind());
diff --git a/src/Compilers/Core/CodeAnalysisTest/LineMappingTests.cs b/src/Compilers/Core/CodeAnalysisTest/LineMappingTests.cs
new file mode 100644
index 0000000000000..4609e8718c291
--- /dev/null
+++ b/src/Compilers/Core/CodeAnalysisTest/LineMappingTests.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using Microsoft.CodeAnalysis.Text;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.UnitTests
+{
+ public class LineMappingTests
+ {
+ [Fact]
+ public void Equality()
+ {
+ var lineMappings = new LineMapping[]
+ {
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: true)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 2)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(2, 2)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 1), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(1, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("file.cs", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), 0, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 2)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 0), new LinePosition(2, 2)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(0, 1), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ new LineMapping(new LinePositionSpan(new LinePosition(1, 0), new LinePosition(1, 1)), null, new FileLinePositionSpan("", new LinePositionSpan(new LinePosition(0, 0), new LinePosition(1, 1)), hasMappedPath: false)),
+ };
+ var equalityUnits = lineMappings.SelectMany((left, leftIndex) => lineMappings.Select((right, rightIndex) => CreateEqualityUnit(left, leftIndex, right, rightIndex))).ToArray();
+ EqualityUtil.RunAll(
+ (left, right) => left == right,
+ (left, right) => left != right,
+ equalityUnits);
+
+ static EqualityUnit CreateEqualityUnit(LineMapping left, int leftIndex, LineMapping right, int rightIndex)
+ {
+ var leftUnit = EqualityUnit.Create(left);
+ return (leftIndex == rightIndex) ? leftUnit.WithEqualValues(right) : leftUnit.WithNotEqualValues(right);
+ }
+ }
+ }
+}
diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
index f57c54f93a2d1..c245c3fbfd1c2 100644
--- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
@@ -50,18 +50,18 @@ Microsoft.CodeAnalysis.GeneratorPostInitializationContext.CancellationToken.get
Microsoft.CodeAnalysis.GeneratorPostInitializationContext.GeneratorPostInitializationContext() -> void
Microsoft.CodeAnalysis.IMethodSymbol.MethodImplementationFlags.get -> System.Reflection.MethodImplAttributes
Microsoft.CodeAnalysis.ITypeSymbol.IsRecord.get -> bool
-Microsoft.CodeAnalysis.Operations.ISwitchExpressionOperation.IsExhaustive.get -> bool
Microsoft.CodeAnalysis.LineMapping
-Microsoft.CodeAnalysis.LineMapping.Deconstruct(out Microsoft.CodeAnalysis.Text.LinePositionSpan span, out Microsoft.CodeAnalysis.FileLinePositionSpan mappedSpan) -> void
+Microsoft.CodeAnalysis.LineMapping.CharacterOffset.get -> int?
Microsoft.CodeAnalysis.LineMapping.Equals(Microsoft.CodeAnalysis.LineMapping other) -> bool
Microsoft.CodeAnalysis.LineMapping.IsHidden.get -> bool
Microsoft.CodeAnalysis.LineMapping.LineMapping() -> void
-Microsoft.CodeAnalysis.LineMapping.LineMapping(Microsoft.CodeAnalysis.Text.LinePositionSpan span, Microsoft.CodeAnalysis.FileLinePositionSpan mappedSpan) -> void
+Microsoft.CodeAnalysis.LineMapping.LineMapping(Microsoft.CodeAnalysis.Text.LinePositionSpan span, int? characterOffset, Microsoft.CodeAnalysis.FileLinePositionSpan mappedSpan) -> void
Microsoft.CodeAnalysis.LineMapping.MappedSpan.get -> Microsoft.CodeAnalysis.FileLinePositionSpan
Microsoft.CodeAnalysis.LineMapping.Span.get -> Microsoft.CodeAnalysis.Text.LinePositionSpan
override Microsoft.CodeAnalysis.LineMapping.Equals(object? obj) -> bool
override Microsoft.CodeAnalysis.LineMapping.GetHashCode() -> int
override Microsoft.CodeAnalysis.LineMapping.ToString() -> string?
+Microsoft.CodeAnalysis.Operations.ISwitchExpressionOperation.IsExhaustive.get -> bool
Microsoft.CodeAnalysis.Operations.OperationWalker
Microsoft.CodeAnalysis.Operations.OperationWalker.OperationWalker() -> void
Microsoft.CodeAnalysis.SourceProductionContext
diff --git a/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.LineMappingEntry.cs b/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.LineMappingEntry.cs
index eff85cb1d1b61..111fe5aeca5b4 100644
--- a/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.LineMappingEntry.cs
+++ b/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.LineMappingEntry.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis
{
@@ -29,6 +31,11 @@ public enum PositionState : byte
///
Remapped,
+ ///
+ /// Used in C# for spans inside of #line (startLine, startChar) - (endLine, endChar) charOffset directive
+ ///
+ RemappedSpan,
+
///
/// Used in VB for spans inside of a #ExternalSource directive that followed an unknown span
///
@@ -56,6 +63,12 @@ public enum PositionState : byte
// 0-based line it maps to.
public readonly int MappedLine;
+ // 0-based mapped span from enhanced #line directive.
+ public readonly LinePositionSpan MappedSpan;
+
+ // optional 0-based character offset from enhanced #line directive.
+ public readonly int? UnmappedCharacterOffset;
+
// raw value from #line or #ExternalDirective, may be null
public readonly string? MappedPathOpt;
@@ -66,6 +79,8 @@ public LineMappingEntry(int unmappedLine)
{
this.UnmappedLine = unmappedLine;
this.MappedLine = unmappedLine;
+ this.MappedSpan = default;
+ this.UnmappedCharacterOffset = null;
this.MappedPathOpt = null;
this.State = PositionState.Unmapped;
}
@@ -76,12 +91,30 @@ public LineMappingEntry(
string? mappedPathOpt,
PositionState state)
{
+ Debug.Assert(state != PositionState.RemappedSpan);
+
this.UnmappedLine = unmappedLine;
this.MappedLine = mappedLine;
+ this.MappedSpan = default;
+ this.UnmappedCharacterOffset = null;
this.MappedPathOpt = mappedPathOpt;
this.State = state;
}
+ public LineMappingEntry(
+ int unmappedLine,
+ LinePositionSpan mappedSpan,
+ int? unmappedCharacterOffset,
+ string? mappedPathOpt)
+ {
+ this.UnmappedLine = unmappedLine;
+ this.MappedLine = -1;
+ this.MappedSpan = mappedSpan;
+ this.UnmappedCharacterOffset = unmappedCharacterOffset;
+ this.MappedPathOpt = mappedPathOpt;
+ this.State = PositionState.RemappedSpan;
+ }
+
public int CompareTo(LineMappingEntry other)
=> UnmappedLine.CompareTo(other.UnmappedLine);
diff --git a/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.cs b/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.cs
index 3ad2f7bdbc6cc..ed0ed6793fd1d 100644
--- a/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.cs
+++ b/src/Compilers/Core/Portable/Syntax/LineDirectiveMap.cs
@@ -55,18 +55,49 @@ public FileLinePositionSpan TranslateSpan(SourceText sourceText, string treeFile
return TranslateSpan(entry, treeFilePath, unmappedStartPos, unmappedEndPos);
}
- protected FileLinePositionSpan TranslateSpan(LineMappingEntry entry, string treeFilePath, LinePosition unmappedStartPos, LinePosition unmappedEndPos)
+ protected FileLinePositionSpan TranslateSpan(in LineMappingEntry entry, string treeFilePath, LinePosition unmappedStartPos, LinePosition unmappedEndPos)
{
string path = entry.MappedPathOpt ?? treeFilePath;
- int mappedStartLine = unmappedStartPos.Line - entry.UnmappedLine + entry.MappedLine;
- int mappedEndLine = unmappedEndPos.Line - entry.UnmappedLine + entry.MappedLine;
-
- return new FileLinePositionSpan(
- path,
- new LinePositionSpan(
- (mappedStartLine == -1) ? new LinePosition(unmappedStartPos.Character) : new LinePosition(mappedStartLine, unmappedStartPos.Character),
- (mappedEndLine == -1) ? new LinePosition(unmappedEndPos.Character) : new LinePosition(mappedEndLine, unmappedEndPos.Character)),
- hasMappedPath: entry.MappedPathOpt != null);
+ var span = entry.State == PositionState.RemappedSpan ?
+ TranslateEnhancedLineDirectiveSpan(entry, unmappedStartPos, unmappedEndPos) :
+ TranslateLineDirectiveSpan(entry, unmappedStartPos, unmappedEndPos);
+ return new FileLinePositionSpan(path, span, hasMappedPath: entry.MappedPathOpt != null);
+ }
+
+ private static LinePositionSpan TranslateLineDirectiveSpan(in LineMappingEntry entry, LinePosition unmappedStartPos, LinePosition unmappedEndPos)
+ {
+ return new LinePositionSpan(translatePosition(entry, unmappedStartPos), translatePosition(entry, unmappedEndPos));
+
+ static LinePosition translatePosition(in LineMappingEntry entry, LinePosition unmapped)
+ {
+ int mappedLine = unmapped.Line - entry.UnmappedLine + entry.MappedLine;
+ return (mappedLine == -1) ? new LinePosition(unmapped.Character) : new LinePosition(mappedLine, unmapped.Character);
+ }
+ }
+
+ private static LinePositionSpan TranslateEnhancedLineDirectiveSpan(in LineMappingEntry entry, LinePosition unmappedStartPos, LinePosition unmappedEndPos)
+ {
+ // A span starting on the first line, at or before 'UnmappedCharacterOffset' is
+ // mapped to the entire 'MappedSpan', regardless of the size of the unmapped span,
+ // even if the unmapped span ends before 'UnmappedCharacterOffset'.
+ if (unmappedStartPos.Line == entry.UnmappedLine &&
+ unmappedStartPos.Character <= entry.UnmappedCharacterOffset.GetValueOrDefault())
+ {
+ return entry.MappedSpan;
+ }
+
+ // A span starting on the first line after 'UnmappedCharacterOffset', or starting on
+ // a subseqent line, is mapped to a span of corresponding size.
+ return new LinePositionSpan(translatePosition(entry, unmappedStartPos), translatePosition(entry, unmappedEndPos));
+
+ static LinePosition translatePosition(in LineMappingEntry entry, LinePosition unmapped)
+ {
+ return new LinePosition(
+ unmapped.Line - entry.UnmappedLine + entry.MappedSpan.Start.Line,
+ unmapped.Line == entry.UnmappedLine ?
+ entry.MappedSpan.Start.Character + unmapped.Character - entry.UnmappedCharacterOffset.GetValueOrDefault() :
+ unmapped.Character);
+ }
}
///
@@ -151,26 +182,6 @@ current.State is PositionState.Unmapped or PositionState.Unknown &&
current.MappedLine == 0 &&
current.MappedPathOpt == null);
- LineMapping CreateCurrentEntryMapping(in LineMappingEntry entry, int unmappedEndLine, int lineLength, int currentIndex)
- {
- var unmapped = new LinePositionSpan(
- new LinePosition(entry.UnmappedLine, character: 0),
- new LinePosition(unmappedEndLine, lineLength));
-
- var isHidden =
- entry.State == PositionState.Hidden ||
- entry.State == PositionState.Unknown && GetUnknownStateVisibility(currentIndex) == LineVisibility.Hidden;
-
- var mapped = isHidden ? default : new FileLinePositionSpan(
- entry.MappedPathOpt ?? string.Empty,
- new LinePositionSpan(
- new LinePosition(entry.MappedLine, character: 0),
- new LinePosition(entry.MappedLine + unmappedEndLine - entry.UnmappedLine, lineLength)),
- hasMappedPath: entry.MappedPathOpt != null);
-
- return new LineMapping(unmapped, mapped);
- }
-
for (int i = 1; i < Entries.Length; i++)
{
var next = Entries[i];
@@ -197,7 +208,7 @@ LineMapping CreateCurrentEntryMapping(in LineMappingEntry entry, int unmappedEnd
var endLine = lines[unmappedEndLine];
int lineLength = endLine.EndIncludingLineBreak - endLine.Start;
- yield return CreateCurrentEntryMapping(current, unmappedEndLine, lineLength, currentIndex: i - 1);
+ yield return CreateLineMapping(current, unmappedEndLine, lineLength, currentIndex: i - 1);
}
current = next;
@@ -218,8 +229,38 @@ LineMapping CreateCurrentEntryMapping(in LineMappingEntry entry, int unmappedEnd
int lineLength = lastLine.EndIncludingLineBreak - lastLine.Start;
int unmappedEndLine = lastLine.LineNumber;
- yield return CreateCurrentEntryMapping(current, unmappedEndLine, lineLength, currentIndex: Entries.Length - 1);
+ yield return CreateLineMapping(current, unmappedEndLine, lineLength, currentIndex: Entries.Length - 1);
+ }
+ }
+
+ private LineMapping CreateLineMapping(in LineMappingEntry entry, int unmappedEndLine, int lineLength, int currentIndex)
+ {
+ var unmapped = new LinePositionSpan(
+ new LinePosition(entry.UnmappedLine, character: 0),
+ new LinePosition(unmappedEndLine, lineLength));
+
+ if (entry.State == PositionState.Hidden ||
+ entry.State == PositionState.Unknown && GetUnknownStateVisibility(currentIndex) == LineVisibility.Hidden)
+ {
+ return new LineMapping(unmapped, characterOffset: null, mappedSpan: default);
}
+
+ string path = entry.MappedPathOpt ?? string.Empty;
+ bool hasMappedPath = entry.MappedPathOpt != null;
+
+ if (entry.State == PositionState.RemappedSpan)
+ {
+ return new LineMapping(
+ unmapped,
+ characterOffset: entry.UnmappedCharacterOffset,
+ new FileLinePositionSpan(path, entry.MappedSpan, hasMappedPath));
+ }
+
+ var mappedSpan = new LinePositionSpan(
+ new LinePosition(entry.MappedLine, character: 0),
+ new LinePosition(entry.MappedLine + unmappedEndLine - entry.UnmappedLine, lineLength));
+ var mapped = new FileLinePositionSpan(path, mappedSpan, hasMappedPath);
+ return new LineMapping(unmapped, characterOffset: null, mapped);
}
}
}
diff --git a/src/Compilers/Core/Portable/Syntax/LineMapping.cs b/src/Compilers/Core/Portable/Syntax/LineMapping.cs
index c6be68d43339d..a481c4dc45bcf 100644
--- a/src/Compilers/Core/Portable/Syntax/LineMapping.cs
+++ b/src/Compilers/Core/Portable/Syntax/LineMapping.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.Serialization;
+using System.Text;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
@@ -19,6 +19,11 @@ namespace Microsoft.CodeAnalysis
///
public readonly LinePositionSpan Span { get; }
+ ///
+ /// The optional offset in the syntax tree for the line immediately following an enhanced #line directive in C#.
+ ///
+ public readonly int? CharacterOffset { get; }
+
///
/// If the line mapping directive maps the span into an explicitly specified file the is true.
/// If the path is not mapped is empty and is false.
@@ -26,18 +31,13 @@ namespace Microsoft.CodeAnalysis
///
public readonly FileLinePositionSpan MappedSpan { get; }
- public LineMapping(LinePositionSpan span, FileLinePositionSpan mappedSpan)
+ public LineMapping(LinePositionSpan span, int? characterOffset, FileLinePositionSpan mappedSpan)
{
Span = span;
+ CharacterOffset = characterOffset;
MappedSpan = mappedSpan;
}
- public void Deconstruct(out LinePositionSpan span, out FileLinePositionSpan mappedSpan)
- {
- span = Span;
- mappedSpan = MappedSpan;
- }
-
///
/// True if the line mapping marks hidden code.
///
@@ -48,10 +48,10 @@ public override bool Equals(object? obj)
=> obj is LineMapping other && Equals(other);
public bool Equals(LineMapping other)
- => Span.Equals(other.Span) && MappedSpan.Equals(other.MappedSpan);
+ => Span.Equals(other.Span) && CharacterOffset.Equals(other.CharacterOffset) && MappedSpan.Equals(other.MappedSpan);
public override int GetHashCode()
- => Hash.Combine(Span.GetHashCode(), MappedSpan.GetHashCode());
+ => Hash.Combine(Hash.Combine(Span.GetHashCode(), CharacterOffset.GetHashCode()), MappedSpan.GetHashCode());
public static bool operator ==(LineMapping left, LineMapping right)
=> left.Equals(right);
@@ -60,6 +60,17 @@ public override int GetHashCode()
=> !(left == right);
public override string? ToString()
- => $"{Span} -> {MappedSpan}";
+ {
+ var builder = new StringBuilder();
+ builder.Append(Span);
+ if (CharacterOffset.HasValue)
+ {
+ builder.Append(",");
+ builder.Append(CharacterOffset.GetValueOrDefault());
+ }
+ builder.Append(" -> ");
+ builder.Append(MappedSpan);
+ return builder.ToString();
+ }
}
}
diff --git a/src/Compilers/Test/Core/TestResource.resx b/src/Compilers/Test/Core/TestResource.resx
index c337fa629026e..92ff5df0788cc 100644
--- a/src/Compilers/Test/Core/TestResource.resx
+++ b/src/Compilers/Test/Core/TestResource.resx
@@ -867,7 +867,9 @@ namespace Comments.XmlComments.UndocumentedKeywords
#line 6
#line 2 "test.cs"
#line default
-#line hidden
+#line hidden
+#line (1, 1) - (2, 2) 3 "test.cs"
+
Option Infer On
diff --git a/src/Compilers/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.vbproj b/src/Compilers/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.vbproj
index 840b7ecd76e75..a4e3694d5dca4 100644
--- a/src/Compilers/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.vbproj
+++ b/src/Compilers/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.vbproj
@@ -8,7 +8,7 @@
..\BasicCodeAnalysisRules.ruleset
true
- partial
+ partial
true
diff --git a/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj b/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj
index 37cc1a409ee8d..71eb76a34f9e7 100644
--- a/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj
+++ b/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj
@@ -6,7 +6,7 @@
Microsoft.CodeAnalysis.Editor.CSharp
netcoreapp3.1;netstandard2.0
true
- partial
+ partial
true
diff --git a/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj b/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj
index d75f775bae394..134ee1de0e3d7 100644
--- a/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj
+++ b/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj
@@ -7,7 +7,7 @@
netcoreapp3.1;netstandard2.0
true
$(DefineConstants);EDITOR_FEATURES
- partial
+ partial
Microsoft.CodeAnalysis.EditorFeatures.Common
diff --git a/src/EditorFeatures/Text/Microsoft.CodeAnalysis.EditorFeatures.Text.csproj b/src/EditorFeatures/Text/Microsoft.CodeAnalysis.EditorFeatures.Text.csproj
index 98ac2d73b3bf1..e5cccc88f95fc 100644
--- a/src/EditorFeatures/Text/Microsoft.CodeAnalysis.EditorFeatures.Text.csproj
+++ b/src/EditorFeatures/Text/Microsoft.CodeAnalysis.EditorFeatures.Text.csproj
@@ -5,7 +5,7 @@
Library
Microsoft.CodeAnalysis.Text
netcoreapp3.1;netstandard2.0
- partial
+ partial
true
diff --git a/src/EditorFeatures/VisualBasic/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.vbproj b/src/EditorFeatures/VisualBasic/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.vbproj
index 9a3cb1ca4f787..528fe72cace76 100644
--- a/src/EditorFeatures/VisualBasic/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.vbproj
+++ b/src/EditorFeatures/VisualBasic/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.vbproj
@@ -5,7 +5,7 @@
Library
netcoreapp3.1;netstandard2.0
- partial
+ partial
true
diff --git a/src/Features/Core/Portable/EditAndContinue/ActiveStatementsMap.cs b/src/Features/Core/Portable/EditAndContinue/ActiveStatementsMap.cs
index 8c72c5ce9ce97..f3ca5140cfa6c 100644
--- a/src/Features/Core/Portable/EditAndContinue/ActiveStatementsMap.cs
+++ b/src/Features/Core/Portable/EditAndContinue/ActiveStatementsMap.cs
@@ -180,8 +180,11 @@ void AddStatement(LinePositionSpan unmappedLineSpan, ActiveStatement activeState
}
var hasAnyLineDirectives = false;
- foreach (var (unmappedSection, mappedSection) in oldTree.GetLineMappings(cancellationToken))
+ foreach (var lineMapping in oldTree.GetLineMappings(cancellationToken))
{
+ var unmappedSection = lineMapping.Span;
+ var mappedSection = lineMapping.MappedSpan;
+
hasAnyLineDirectives = true;
var targetPath = mappedSection.HasMappedPath ? mappedSection.Path : oldTree.FilePath;
diff --git a/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj b/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj
index fad332e9ccc56..7f3239d0f5526 100644
--- a/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj
+++ b/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj
@@ -6,7 +6,7 @@
Microsoft.CodeAnalysis.CSharp
true
netcoreapp3.1;netstandard2.0
- partial
+ partial
true
diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj
index fbf621a2a8872..606559a0d60f3 100644
--- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj
+++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj
@@ -8,7 +8,7 @@
netcoreapp3.1;netstandard2.0
$(DefineConstants);WORKSPACE
true
- partial
+ partial
true
diff --git a/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj b/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj
index 2fc914af44c65..602bb056c19b5 100644
--- a/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj
+++ b/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj
@@ -5,7 +5,7 @@
Library
netcoreapp3.1;netstandard2.0
- partial
+ partial
true