From 6c204846ce9c2f5f299cc2f2e41f080ba1ef4bb1 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 25 Jul 2020 12:11:07 +0200 Subject: [PATCH] Fix trivia handling --- Parser.Tests/ThereAndBackAgain.cs | 31 +++++++++++++++++++++- Parser/Internal/GreenNode.cs | 1 - Parser/Internal/MParserGreen.cs | 7 ++++- Parser/Internal/SyntaxFactory.Generated.cs | 2 +- Parser/Internal/SyntaxNode.Generated.cs | 6 ++--- Parser/Internal/SyntaxNode.cs | 2 +- Parser/Internal/SyntaxTrivia.cs | 1 + Parser/SyntaxDefinition.xml | 2 +- Parser/SyntaxNode.Generated.cs | 8 +++--- Parser/SyntaxTriviaList.cs | 2 ++ 10 files changed, 49 insertions(+), 13 deletions(-) diff --git a/Parser.Tests/ThereAndBackAgain.cs b/Parser.Tests/ThereAndBackAgain.cs index 782f36f..7c9221c 100644 --- a/Parser.Tests/ThereAndBackAgain.cs +++ b/Parser.Tests/ThereAndBackAgain.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using Xunit; namespace Parser.Tests @@ -56,7 +57,35 @@ namespace Parser.Tests Assert.Equal(text, actualText); 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 FilesData() { return Files().Select(fileName => new object[] { fileName }); diff --git a/Parser/Internal/GreenNode.cs b/Parser/Internal/GreenNode.cs index 9a07bc0..a18b838 100644 --- a/Parser/Internal/GreenNode.cs +++ b/Parser/Internal/GreenNode.cs @@ -209,7 +209,6 @@ namespace Parser.Internal } return sb.ToString(); - } } diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index 920575c..32851ba 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -1175,9 +1175,14 @@ namespace Parser.Internal return ParseExpressionStatement(); } - private BlockStatementSyntaxNode ParseBlockStatement() + private BlockStatementSyntaxNode? ParseBlockStatement() { var statements = ParseStatementList(); + if (statements.Length == 0) + { + return null; + } + return Factory.BlockStatementSyntax(statements); } diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index 6280330..77463ca 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -3,7 +3,7 @@ namespace Parser.Internal { internal partial class SyntaxFactory { - public FileSyntaxNode FileSyntax(BlockStatementSyntaxNode body, SyntaxToken endOfFile) + public FileSyntaxNode FileSyntax(BlockStatementSyntaxNode? body, SyntaxToken endOfFile) { return new FileSyntaxNode(body, endOfFile); } diff --git a/Parser/Internal/SyntaxNode.Generated.cs b/Parser/Internal/SyntaxNode.Generated.cs index b020d0e..8bcebfd 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -3,9 +3,9 @@ namespace Parser.Internal { internal class FileSyntaxNode : SyntaxNode { - internal readonly BlockStatementSyntaxNode _body; + internal readonly BlockStatementSyntaxNode? _body; internal readonly SyntaxToken _endOfFile; - internal FileSyntaxNode(BlockStatementSyntaxNode body, SyntaxToken endOfFile): base(TokenKind.File) + internal FileSyntaxNode(BlockStatementSyntaxNode? body, SyntaxToken endOfFile): base(TokenKind.File) { Slots = 2; this.AdjustWidth(body); @@ -14,7 +14,7 @@ namespace Parser.Internal _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; this.AdjustWidth(body); diff --git a/Parser/Internal/SyntaxNode.cs b/Parser/Internal/SyntaxNode.cs index 9486928..a94e8fb 100644 --- a/Parser/Internal/SyntaxNode.cs +++ b/Parser/Internal/SyntaxNode.cs @@ -51,7 +51,7 @@ namespace Parser.Internal return builder.ToString(); } - public override string FullText => CollectFullText(); + //public override string FullText => CollectFullText(); public override GreenNode? LeadingTriviaCore => throw new NotImplementedException(); public override GreenNode? TrailingTriviaCore => throw new NotImplementedException(); diff --git a/Parser/Internal/SyntaxTrivia.cs b/Parser/Internal/SyntaxTrivia.cs index e577bb3..9abec4c 100644 --- a/Parser/Internal/SyntaxTrivia.cs +++ b/Parser/Internal/SyntaxTrivia.cs @@ -20,6 +20,7 @@ namespace Parser.Internal } public override string Text => _text; + public override string FullText => _text; public int Width => _text.Length; public override GreenNode? GetSlot(int i) diff --git a/Parser/SyntaxDefinition.xml b/Parser/SyntaxDefinition.xml index be2d64f..68022df 100644 --- a/Parser/SyntaxDefinition.xml +++ b/Parser/SyntaxDefinition.xml @@ -1,7 +1,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index 9bc5b65..d1b0431 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -16,12 +16,12 @@ namespace Parser } } - public BlockStatementSyntaxNode Body + public BlockStatementSyntaxNode? Body { get { - var red = this.GetRed(ref this._body!, 0); - return red is null ? throw new System.Exception("body cannot be null.") : (BlockStatementSyntaxNode)red; + var red = this.GetRed(ref this._body, 0); + return red is null ? default : (BlockStatementSyntaxNode)red; } } @@ -29,7 +29,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _body!, 0), _ => null + 0 => GetRed(ref _body, 0), _ => null } ; diff --git a/Parser/SyntaxTriviaList.cs b/Parser/SyntaxTriviaList.cs index 61eadd7..c76e9b1 100644 --- a/Parser/SyntaxTriviaList.cs +++ b/Parser/SyntaxTriviaList.cs @@ -36,6 +36,8 @@ namespace Parser } } + public string FullText => Node?.FullText ?? string.Empty; + public IEnumerator GetEnumerator() { for (var i = 0; i < Count; i++)