Fix trivia handling

This commit is contained in:
Alexander Luzgarev 2020-07-25 12:11:07 +02:00
parent c70e94d166
commit 6c204846ce
10 changed files with 49 additions and 13 deletions

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using Xunit; using Xunit;
namespace Parser.Tests namespace Parser.Tests
@ -57,6 +58,34 @@ namespace Parser.Tests
Assert.Equal(text.Length, actualWidth); Assert.Equal(text.Length, actualWidth);
} }
[Theory]
[MemberData(nameof(FilesData))]
public void TestLeadingAndTrailingTrivia(string fileName)
{
var text = File.ReadAllText(fileName);
var window = new TextWindowWithNull(text, fileName);
var parser = CreateParser(window);
var tree = parser.Parse();
var sb = new StringBuilder();
var maybeLeadingTrivia = tree.Root.LeadingTrivia;
var maybeTrailingTrivia = tree.Root.TrailingTrivia;
if (maybeLeadingTrivia is SyntaxTriviaList leadingTrivia)
{
sb.Append(leadingTrivia.FullText);
}
sb.Append(tree.Root.Text);
if (maybeTrailingTrivia is SyntaxTriviaList trailingTrivia)
{
sb.Append(trailingTrivia.FullText);
}
var actualText = sb.ToString();
Assert.Equal(text, actualText);
}
public static IEnumerable<object[]> FilesData() public static IEnumerable<object[]> FilesData()
{ {
return Files().Select(fileName => new object[] { fileName }); return Files().Select(fileName => new object[] { fileName });

View File

@ -209,7 +209,6 @@ namespace Parser.Internal
} }
return sb.ToString(); return sb.ToString();
} }
} }

View File

@ -1175,9 +1175,14 @@ namespace Parser.Internal
return ParseExpressionStatement(); return ParseExpressionStatement();
} }
private BlockStatementSyntaxNode ParseBlockStatement() private BlockStatementSyntaxNode? ParseBlockStatement()
{ {
var statements = ParseStatementList(); var statements = ParseStatementList();
if (statements.Length == 0)
{
return null;
}
return Factory.BlockStatementSyntax(statements); return Factory.BlockStatementSyntax(statements);
} }

View File

@ -3,7 +3,7 @@ namespace Parser.Internal
{ {
internal partial class SyntaxFactory internal partial class SyntaxFactory
{ {
public FileSyntaxNode FileSyntax(BlockStatementSyntaxNode body, SyntaxToken endOfFile) public FileSyntaxNode FileSyntax(BlockStatementSyntaxNode? body, SyntaxToken endOfFile)
{ {
return new FileSyntaxNode(body, endOfFile); return new FileSyntaxNode(body, endOfFile);
} }

View File

@ -3,9 +3,9 @@ namespace Parser.Internal
{ {
internal class FileSyntaxNode : SyntaxNode internal class FileSyntaxNode : SyntaxNode
{ {
internal readonly BlockStatementSyntaxNode _body; internal readonly BlockStatementSyntaxNode? _body;
internal readonly SyntaxToken _endOfFile; internal readonly SyntaxToken _endOfFile;
internal FileSyntaxNode(BlockStatementSyntaxNode body, SyntaxToken endOfFile): base(TokenKind.File) internal FileSyntaxNode(BlockStatementSyntaxNode? body, SyntaxToken endOfFile): base(TokenKind.File)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(body); this.AdjustWidth(body);
@ -14,7 +14,7 @@ namespace Parser.Internal
_endOfFile = endOfFile; _endOfFile = endOfFile;
} }
internal FileSyntaxNode(BlockStatementSyntaxNode body, SyntaxToken endOfFile, TokenDiagnostic[] diagnostics): base(TokenKind.File, diagnostics) internal FileSyntaxNode(BlockStatementSyntaxNode? body, SyntaxToken endOfFile, TokenDiagnostic[] diagnostics): base(TokenKind.File, diagnostics)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(body); this.AdjustWidth(body);

View File

@ -51,7 +51,7 @@ namespace Parser.Internal
return builder.ToString(); return builder.ToString();
} }
public override string FullText => CollectFullText(); //public override string FullText => CollectFullText();
public override GreenNode? LeadingTriviaCore => throw new NotImplementedException(); public override GreenNode? LeadingTriviaCore => throw new NotImplementedException();
public override GreenNode? TrailingTriviaCore => throw new NotImplementedException(); public override GreenNode? TrailingTriviaCore => throw new NotImplementedException();

View File

@ -20,6 +20,7 @@ namespace Parser.Internal
} }
public override string Text => _text; public override string Text => _text;
public override string FullText => _text;
public int Width => _text.Length; public int Width => _text.Length;
public override GreenNode? GetSlot(int i) public override GreenNode? GetSlot(int i)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Syntax xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Syntax xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Class Name="FileSyntaxNode" BaseClass="SyntaxNode" Kind="File"> <Class Name="FileSyntaxNode" BaseClass="SyntaxNode" Kind="File">
<Field Type="BlockStatementSyntaxNode" Name="body" /> <Field Type="BlockStatementSyntaxNode" Name="body" Nullable="true"/>
<Field Type="SyntaxToken" Name="endOfFile" /> <Field Type="SyntaxToken" Name="endOfFile" />
</Class> </Class>
<Class Name="BlockStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="BlockStatement"> <Class Name="BlockStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="BlockStatement">

View File

@ -16,12 +16,12 @@ namespace Parser
} }
} }
public BlockStatementSyntaxNode Body public BlockStatementSyntaxNode? Body
{ {
get get
{ {
var red = this.GetRed(ref this._body!, 0); var red = this.GetRed(ref this._body, 0);
return red is null ? throw new System.Exception("body cannot be null.") : (BlockStatementSyntaxNode)red; return red is null ? default : (BlockStatementSyntaxNode)red;
} }
} }
@ -29,7 +29,7 @@ namespace Parser
{ {
return i switch return i switch
{ {
0 => GetRed(ref _body!, 0), _ => null 0 => GetRed(ref _body, 0), _ => null
} }
; ;

View File

@ -36,6 +36,8 @@ namespace Parser
} }
} }
public string FullText => Node?.FullText ?? string.Empty;
public IEnumerator<SyntaxTrivia> GetEnumerator() public IEnumerator<SyntaxTrivia> GetEnumerator()
{ {
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)