From 423a25e255da66efb3aebe86310c8d4eb25869ad Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:07:34 -0500 Subject: [PATCH 01/21] Update versions --- Source/Lib/Common/Luthetus.Common.RazorLib.csproj | 2 +- .../CSharp/Luthetus.CompilerServices.CSharp.csproj | 2 +- Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj | 2 +- .../Shareds/Displays/Internals/IdeInfoDisplay.razor | 8 ++++++++ Source/Lib/TextEditor/Luthetus.TextEditor.RazorLib.csproj | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/Lib/Common/Luthetus.Common.RazorLib.csproj b/Source/Lib/Common/Luthetus.Common.RazorLib.csproj index b20daf2f0..ed4fa95f8 100644 --- a/Source/Lib/Common/Luthetus.Common.RazorLib.csproj +++ b/Source/Lib/Common/Luthetus.Common.RazorLib.csproj @@ -7,7 +7,7 @@ Luthetus Common A repository containing Blazor Components I've made which I commonly use in other projects. Luthetus.Common - 3.3.0 + 3.4.0 Hunter Freeman DotNet CSharp Blazor RazorComponents diff --git a/Source/Lib/CompilerServices/CSharp/Luthetus.CompilerServices.CSharp.csproj b/Source/Lib/CompilerServices/CSharp/Luthetus.CompilerServices.CSharp.csproj index 0f4eb070e..c111daf0f 100644 --- a/Source/Lib/CompilerServices/CSharp/Luthetus.CompilerServices.CSharp.csproj +++ b/Source/Lib/CompilerServices/CSharp/Luthetus.CompilerServices.CSharp.csproj @@ -7,7 +7,7 @@ Luthetus Compiler Service C# A C# implementation of the ICompilerService interface, which comes from the "Luthetus.TextEditor" repository. Luthetus.CompilerServices.CSharp - 3.3.0 + 3.4.0 Hunter Freeman DotNet CSharp Blazor RazorComponents diff --git a/Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj b/Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj index 3377053a6..79a2d82bc 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj +++ b/Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 0.9.7.3 + 0.9.7.4 diff --git a/Source/Lib/Ide/Ide.RazorLib/Shareds/Displays/Internals/IdeInfoDisplay.razor b/Source/Lib/Ide/Ide.RazorLib/Shareds/Displays/Internals/IdeInfoDisplay.razor index c507fb040..0cfd8d43f 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Shareds/Displays/Internals/IdeInfoDisplay.razor +++ b/Source/Lib/Ide/Ide.RazorLib/Shareds/Displays/Internals/IdeInfoDisplay.razor @@ -172,6 +172,14 @@ Recent Changes:
+
v 0.9.7.4 (WIP_DATE)
+
    +
  • + WIP_DESCRIPTION +
  • +
+
+
v 0.9.7.3 (2024-11-28)
  • diff --git a/Source/Lib/TextEditor/Luthetus.TextEditor.RazorLib.csproj b/Source/Lib/TextEditor/Luthetus.TextEditor.RazorLib.csproj index 01f63be79..6bc91faa5 100644 --- a/Source/Lib/TextEditor/Luthetus.TextEditor.RazorLib.csproj +++ b/Source/Lib/TextEditor/Luthetus.TextEditor.RazorLib.csproj @@ -7,7 +7,7 @@ Luthetus TextEditor A text editor written using Blazor. Contains API for syntax highlighting, and ICompilerService integration. Luthetus.TextEditor - 3.3.0 + 3.4.0 Hunter Freeman DotNet CSharp Blazor RazorComponents From e2e166e6122581802382cd11d62c23684064119e Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:24:03 -0500 Subject: [PATCH 02/21] Goal: Track the OpenBraceToken and CloseBraceToken pairs that occur in the text. --- .../CSharp/SmokeTests/Lexers/LexerTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs index a2d4c526f..d781354f3 100644 --- a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs +++ b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs @@ -7,6 +7,32 @@ namespace Luthetus.CompilerServices.CSharp.Tests.SmokeTests.Lexers; public class LexerTests { + /// + /// Goal: Track the OpenBraceToken and CloseBraceToken pairs that occur in the text. (2024-12-03) + /// + /// Purpose: Expected to be a noticeable optimization to the Parser speed. + /// + /// Measurements: + /// - Before: + /// - After: + /// + /// Conclusion: + /// + /// ================== + /// + /// + /// + /// It could be useful to add a timer to the 'ProgressBarModel.cs'. + /// + /// Just by tracking the startingDateTime and the (endDateTime ?? currentDateTime), + /// then every render of the notification, the difference between them can be displayed. + /// + [Fact] + public void TrackBraceTokenPairs() + { + throw new NotImplementedException(); + } + [Fact] public void LEX_ArraySyntaxToken() { From 383253db9d8549c9200b5e68ec4ec08e3c4088aa Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:38:05 -0500 Subject: [PATCH 03/21] String interpolated, different color for the expressions --- .../Displays/ProgressBarDisplay.razor | 7 +- .../Reactives/Models/ProgressBarModel.cs | 10 ++ .../CSharp/LexerCase/CSharpLexer.cs | 93 +++++++++++++- .../CSharp/SmokeTests/Lexers/LexerTests.cs | 116 +++++++++++++++++- 4 files changed, 219 insertions(+), 7 deletions(-) diff --git a/Source/Lib/Common/Reactives/Displays/ProgressBarDisplay.razor b/Source/Lib/Common/Reactives/Displays/ProgressBarDisplay.razor index f3256e9bd..51a1073a2 100644 --- a/Source/Lib/Common/Reactives/Displays/ProgressBarDisplay.razor +++ b/Source/Lib/Common/Reactives/Displays/ProgressBarDisplay.razor @@ -23,7 +23,11 @@ fillWidthInPercentage -= cancelButtonWidthInPercentage; } -
    +
    + @($"{localProgressBarModel.GetTimeElapsed().TotalSeconds:N3}") seconds +
    + +
    @@ -65,7 +69,6 @@
    }
    - @if (!string.IsNullOrWhiteSpace(localProgressBarModel.Message)) { diff --git a/Source/Lib/Common/Reactives/Models/ProgressBarModel.cs b/Source/Lib/Common/Reactives/Models/ProgressBarModel.cs index e79fa0150..2f3a3738e 100644 --- a/Source/Lib/Common/Reactives/Models/ProgressBarModel.cs +++ b/Source/Lib/Common/Reactives/Models/ProgressBarModel.cs @@ -20,6 +20,8 @@ public ProgressBarModel(double decimalPercentProgress, string? message) { DecimalPercentProgress = decimalPercentProgress; Message = message; + + DateTimeStart = DateTime.UtcNow; } private Task? _cancelTask; @@ -27,6 +29,8 @@ public ProgressBarModel(double decimalPercentProgress, string? message) public double DecimalPercentProgress { get; private set; } public string? Message { get; private set; } public string? SecondaryMessage { get; private set; } + public DateTime DateTimeStart { get; set; } + public DateTime? DateTimeEnd { get; set; } public bool IsCancellable => OnCancelFunc is not null; public bool IsCancelled { get; set; } public bool IntentToCancel { get; private set; } @@ -107,12 +111,18 @@ public void Cancel() } }); } + + public TimeSpan GetTimeElapsed() + { + return (DateTimeEnd ?? DateTime.UtcNow) - DateTimeStart; + } public void Dispose() { lock (_progressLock) { IsDisposed = true; + DateTimeEnd = DateTime.UtcNow; ProgressChanged?.Invoke(true); } } diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index bc6d41ca6..7d4da9964 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -1,9 +1,11 @@ using System.Collections.Immutable; -using Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Tokens; +using Luthetus.TextEditor.RazorLib.Lexers.Models; using Luthetus.TextEditor.RazorLib.CompilerServices; +using Luthetus.TextEditor.RazorLib.CompilerServices.Syntax; +using Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Tokens; using Luthetus.TextEditor.RazorLib.CompilerServices.GenericLexer.Decoration; -using Luthetus.TextEditor.RazorLib.Lexers.Models; using Luthetus.TextEditor.RazorLib.CompilerServices.Implementations; +using Luthetus.TextEditor.RazorLib.CompilerServices.Utility; namespace Luthetus.CompilerServices.CSharp.LexerCase; @@ -174,7 +176,10 @@ public override void Lex() LexerUtils.LexCloseSquareBracketToken(_stringWalker, _syntaxTokenList); break; case '$': - LexerUtils.LexDollarSignToken(_stringWalker, _syntaxTokenList); + if (_stringWalker.NextCharacter == '"') + LexStringInterpolation(_stringWalker, _syntaxTokenList); + else + LexerUtils.LexDollarSignToken(_stringWalker, _syntaxTokenList); break; case '@': LexerUtils.LexAtToken(_stringWalker, _syntaxTokenList); @@ -206,4 +211,86 @@ public override void Lex() _syntaxTokenList.Add(new EndOfFileToken(endOfFileTextSpan)); } + + private void LexStringInterpolation(StringWalker stringWalker, List syntaxTokenList) + { + var entryPositionIndex = stringWalker.PositionIndex; + + _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character) + _ = stringWalker.ReadCharacter(); // Move past the '"' (double quote character) + + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter == '\"') + { + _ = stringWalker.ReadCharacter(); + break; + } + else if (stringWalker.CurrentCharacter == '\\') + { + if (_escapeCharacterList is not null) + { + _escapeCharacterList.Add(new TextEditorTextSpan( + stringWalker.PositionIndex, + stringWalker.PositionIndex + 2, + (byte)GenericDecorationKind.EscapeCharacter, + stringWalker.ResourceUri, + stringWalker.SourceText)); + } + + // Presuming the escaped text is 2 characters, then read an extra character. + _ = stringWalker.ReadCharacter(); + } + else if (stringWalker.CurrentCharacter == '{') + { + var innerTextSpan = new TextEditorTextSpan( + entryPositionIndex, + stringWalker.PositionIndex, + (byte)GenericDecorationKind.StringLiteral, + stringWalker.ResourceUri, + stringWalker.SourceText); + _syntaxTokenList.Add(new StringLiteralToken(innerTextSpan)); + + LexInterpolatedExpression(stringWalker, syntaxTokenList); + entryPositionIndex = stringWalker.PositionIndex; + } + + _ = stringWalker.ReadCharacter(); + } + + var textSpan = new TextEditorTextSpan( + entryPositionIndex, + stringWalker.PositionIndex, + (byte)GenericDecorationKind.StringLiteral, + stringWalker.ResourceUri, + stringWalker.SourceText); + + _syntaxTokenList.Add(new StringLiteralToken(textSpan)); + } + + private void LexInterpolatedExpression(StringWalker stringWalker, List syntaxTokenList) + { + var entryPositionIndex = stringWalker.PositionIndex; + + _ = stringWalker.ReadCharacter(); // Move past the '{' (open brace character) + + var unmatchedBraceCounter = 1; + + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter == '{') + { + ++unmatchedBraceCounter; + } + else if (stringWalker.CurrentCharacter == '}') + { + if (--unmatchedBraceCounter <= 0) + break; + } + + _ = stringWalker.ReadCharacter(); + } + + _ = stringWalker.ReadCharacter(); + } } \ No newline at end of file diff --git a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs index d781354f3..1bb568b6a 100644 --- a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs +++ b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs @@ -7,13 +7,32 @@ namespace Luthetus.CompilerServices.CSharp.Tests.SmokeTests.Lexers; public class LexerTests { + public class Test + { + public Test(string sourceText) + { + SourceText = sourceText; + ResourceUri = new ResourceUri("./unitTesting.txt"); + Lexer = new CSharpLexer(ResourceUri, SourceText); + Lexer.Lex(); + Parser = new CSharpParser(Lexer); + CompilationUnit = Parser.Parse(); + } + + public string SourceText { get; set; } + public ResourceUri ResourceUri { get; set; } + public CSharpLexer Lexer { get; set; } + public CSharpParser Parser { get; set; } + public CompilationUnit CompilationUnit { get; set; } + } + /// /// Goal: Track the OpenBraceToken and CloseBraceToken pairs that occur in the text. (2024-12-03) /// /// Purpose: Expected to be a noticeable optimization to the Parser speed. /// /// Measurements: - /// - Before: + /// - Before: 63.973 seconds | 65.777 seconds | 64.548 seconds /// - After: /// /// Conclusion: @@ -30,7 +49,60 @@ public class LexerTests [Fact] public void TrackBraceTokenPairs() { - throw new NotImplementedException(); + var test = new Test( +@" +TODO +".ReplaceLineEndings("\n")); + var topCodeBlock = test.CompilationUnit.RootCodeBlockNode; + throw new NotImplementedException(); + } + + /// + /// Include the new escape sequence syntax, + /// i.e.: '""' or two double quotes, is interpreted as one double quotes. + /// + [Fact] + public void InterpolatedString() + { + var test = new Test( +@" +$""a {3 + 3} aa"" +".ReplaceLineEndings("\n")); + var topCodeBlock = test.CompilationUnit.RootCodeBlockNode; + throw new NotImplementedException(); + } + + /// + /// Include the new escape sequence syntax, + /// i.e.: '{{' or two open brace characters, is interpreted as one open brace character (the same is true for close brace). + /// + [Fact] + public void VerbatimString() + { + var test = new Test( +@" +TODO +".ReplaceLineEndings("\n")); + var topCodeBlock = test.CompilationUnit.RootCodeBlockNode; + throw new NotImplementedException(); + } + + /// + /// https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#raw-string-literals + /// Include the new escape sequence syntax, + /// i.e.: the count of double quotes that deliminate the start of the string, is to be matched for the end of the string. + /// As well, interpolation can be modified to by changing the amount of '$' or dollar sign characters + /// that appear prior to the double quotes. + /// + [Fact] + public void RawString() + { + var test = new Test( +@" +TODO +".ReplaceLineEndings("\n")); + var topCodeBlock = test.CompilationUnit.RootCodeBlockNode; + throw new NotImplementedException(); } [Fact] @@ -583,4 +655,44 @@ public void LEX_ClassDefinition() // Tokens: 'public' 'class' 'MyClass' '{' '}' 'EndOfFileToken' Assert.Equal(6, lexer.SyntaxTokenList.Length); } + + + + private void WriteChildrenIndented(ISyntaxNode node, string name = "node") + { + Console.WriteLine($"foreach (var child in {name}.GetChildList())"); + foreach (var child in node.GetChildList()) + { + Console.WriteLine("\t" + child.SyntaxKind); + } + Console.WriteLine(); + } + + private void WriteChildrenIndentedRecursive(ISyntaxNode node, string name = "node", int indentation = 0) + { + var indentationStringBuilder = new StringBuilder(); + for (int i = 0; i < indentation; i++) + indentationStringBuilder.Append('\t'); + + Console.WriteLine($"{indentationStringBuilder.ToString()}{node.SyntaxKind}"); + + // For the child tokens + indentationStringBuilder.Append('\t'); + var childIndentation = indentationStringBuilder.ToString(); + + foreach (var child in node.GetChildList()) + { + if (child is ISyntaxNode syntaxNode) + { + WriteChildrenIndentedRecursive(syntaxNode, "node", indentation + 1); + } + else if (child is ISyntaxToken syntaxToken) + { + Console.WriteLine($"{childIndentation}{child.SyntaxKind}__{syntaxToken.TextSpan.GetText()}"); + } + } + + if (indentation == 0) + Console.WriteLine(); + } } From d7ac96a3c73d2f75c586e707ed41d6b58ea8e3ef Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:52:45 -0500 Subject: [PATCH 04/21] String interpolation: '{{' --- .../CSharp/LexerCase/CSharpLexer.cs | 27 ++++++++++++------- .../CSharp/SmokeTests/Lexers/LexerTests.cs | 6 ++++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 7d4da9964..5dbd113eb 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -243,16 +243,23 @@ private void LexStringInterpolation(StringWalker stringWalker, List Date: Wed, 4 Dec 2024 11:58:29 -0500 Subject: [PATCH 05/21] String interpolation: end with expression edge case --- Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 5dbd113eb..0562b1403 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -257,8 +257,12 @@ private void LexStringInterpolation(StringWalker stringWalker, List Date: Wed, 4 Dec 2024 12:19:38 -0500 Subject: [PATCH 06/21] Verbatim string --- .../CSharp/LexerCase/CSharpLexer.cs | 50 ++++++++++++++++++- .../CSharp/SmokeTests/Lexers/LexerTests.cs | 5 +- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 0562b1403..cb083534a 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -182,7 +182,10 @@ public override void Lex() LexerUtils.LexDollarSignToken(_stringWalker, _syntaxTokenList); break; case '@': - LexerUtils.LexAtToken(_stringWalker, _syntaxTokenList); + if (_stringWalker.NextCharacter == '"') + LexStringVerbatim(_stringWalker, _syntaxTokenList); + else + LexerUtils.LexAtToken(_stringWalker, _syntaxTokenList); break; case ':': LexerUtils.LexColonToken(_stringWalker, _syntaxTokenList); @@ -304,4 +307,49 @@ private void LexInterpolatedExpression(StringWalker stringWalker, List syntaxTokenList) + { + var entryPositionIndex = stringWalker.PositionIndex; + + _ = stringWalker.ReadCharacter(); // Move past the '@' (at character) + _ = stringWalker.ReadCharacter(); // Move past the '"' (double quote character) + + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter == '\"') + { + if (stringWalker.NextCharacter == '\"') + { + if (_escapeCharacterList is not null) + { + _escapeCharacterList.Add(new TextEditorTextSpan( + stringWalker.PositionIndex, + stringWalker.PositionIndex + 2, + (byte)GenericDecorationKind.EscapeCharacter, + stringWalker.ResourceUri, + stringWalker.SourceText)); + } + + _ = stringWalker.ReadCharacter(); + } + else + { + _ = stringWalker.ReadCharacter(); + break; + } + } + + _ = stringWalker.ReadCharacter(); + } + + var textSpan = new TextEditorTextSpan( + entryPositionIndex, + stringWalker.PositionIndex, + (byte)GenericDecorationKind.StringLiteral, + stringWalker.ResourceUri, + stringWalker.SourceText); + + _syntaxTokenList.Add(new StringLiteralToken(textSpan)); + } } \ No newline at end of file diff --git a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs index 04b526da7..b08f94dba 100644 --- a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs +++ b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs @@ -83,10 +83,7 @@ public void InterpolatedString() [Fact] public void VerbatimString() { - var test = new Test( -@" -TODO -".ReplaceLineEndings("\n")); + var test = new Test("var x = \"\n\""); var topCodeBlock = test.CompilationUnit.RootCodeBlockNode; throw new NotImplementedException(); } From 518a1d669cf4bd27f9e6b6a2d823cbb2775d00e8 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 12:44:43 -0500 Subject: [PATCH 07/21] LexStringRaw --- .../CSharp/LexerCase/CSharpLexer.cs | 59 ++++++++++++++++++- .../CSharp/SmokeTests/Lexers/LexerTests.cs | 5 +- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index cb083534a..5a77510a9 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -103,7 +103,17 @@ public override void Lex() LexerUtils.LexCharLiteralToken(_stringWalker, _syntaxTokenList, _escapeCharacterList); break; case '"': - LexerUtils.LexStringLiteralToken(_stringWalker, _syntaxTokenList, _escapeCharacterList); + if (_stringWalker.PeekCharacter(1) == '"' && _stringWalker.PeekCharacter(2) == '"') + { + // At least 3 double quotes are required for a raw string. + // The actual counting of how many quotes will be used as a deliminator + // is done inside the method. + LexStringRaw(_stringWalker, _syntaxTokenList); + } + else + { + LexerUtils.LexStringLiteralToken(_stringWalker, _syntaxTokenList, _escapeCharacterList); + } break; case '/': if (_stringWalker.PeekCharacter(1) == '/') @@ -352,4 +362,51 @@ private void LexStringVerbatim(StringWalker stringWalker, List syn _syntaxTokenList.Add(new StringLiteralToken(textSpan)); } + + private void LexStringRaw(StringWalker stringWalker, List syntaxTokenList) + { + var entryPositionIndex = stringWalker.PositionIndex; + + int countDoubleQuotes = 0; + + // Count the amount of double quotes to be used as the delimiter. + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter != '\"') + break; + + ++countDoubleQuotes; + _ = stringWalker.ReadCharacter(); + } + + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter == '\"') + { + var matchDoubleQuotes = countDoubleQuotes; + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter != '\"') + break; + + _ = stringWalker.ReadCharacter(); + if (--matchDoubleQuotes == 0) + goto foundEndDelimiter; + } + } + + _ = stringWalker.ReadCharacter(); + } + + foundEndDelimiter: + + var textSpan = new TextEditorTextSpan( + entryPositionIndex, + stringWalker.PositionIndex, + (byte)GenericDecorationKind.StringLiteral, + stringWalker.ResourceUri, + stringWalker.SourceText); + + _syntaxTokenList.Add(new StringLiteralToken(textSpan)); + } } \ No newline at end of file diff --git a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs index b08f94dba..10ac776c3 100644 --- a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs +++ b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs @@ -83,7 +83,10 @@ public void InterpolatedString() [Fact] public void VerbatimString() { - var test = new Test("var x = \"\n\""); + var test = new Test( +@" +var y = @""\n""""\t""; +".ReplaceLineEndings("\n"); var topCodeBlock = test.CompilationUnit.RootCodeBlockNode; throw new NotImplementedException(); } From 30327fdb97ca80194369e2f63c646567fa81fc21 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:08:45 -0500 Subject: [PATCH 08/21] LexStringEitherInterpolationAndOrVerbatim(...) --- .../CSharp/LexerCase/CSharpLexer.cs | 118 ++++++++++-------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 5a77510a9..a41b269fb 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -187,15 +187,47 @@ public override void Lex() break; case '$': if (_stringWalker.NextCharacter == '"') - LexStringInterpolation(_stringWalker, _syntaxTokenList); + { + LexStringEitherInterpolationAndOrVerbatim( + _stringWalker, + _syntaxTokenList, + useInterpolation: true, + useVerbatim: false); + } + else if (_stringWalker.PeekCharacter(1) == '@' && _stringWalker.PeekCharacter(2) == '"') + { + LexStringEitherInterpolationAndOrVerbatim( + _stringWalker, + _syntaxTokenList, + useInterpolation: true, + useVerbatim: true); + } else + { LexerUtils.LexDollarSignToken(_stringWalker, _syntaxTokenList); + } break; case '@': if (_stringWalker.NextCharacter == '"') - LexStringVerbatim(_stringWalker, _syntaxTokenList); + { + LexStringEitherInterpolationAndOrVerbatim( + _stringWalker, + _syntaxTokenList, + useInterpolation: false, + useVerbatim: true); + } + else if (_stringWalker.PeekCharacter(1) == '$' && _stringWalker.PeekCharacter(2) == '"') + { + LexStringEitherInterpolationAndOrVerbatim( + _stringWalker, + _syntaxTokenList, + useInterpolation: true, + useVerbatim: true); + } else + { LexerUtils.LexAtToken(_stringWalker, _syntaxTokenList); + } break; case ':': LexerUtils.LexColonToken(_stringWalker, _syntaxTokenList); @@ -225,21 +257,46 @@ public override void Lex() _syntaxTokenList.Add(new EndOfFileToken(endOfFileTextSpan)); } - private void LexStringInterpolation(StringWalker stringWalker, List syntaxTokenList) + private void LexStringEitherInterpolationAndOrVerbatim( + StringWalker stringWalker, + List syntaxTokenList, + bool useInterpolation, + bool useVerbatim) { var entryPositionIndex = stringWalker.PositionIndex; - _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character) + if (useInterpolation) + _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character) + if (useVerbatim) + _ = stringWalker.ReadCharacter(); // Move past the '@' (at character) + _ = stringWalker.ReadCharacter(); // Move past the '"' (double quote character) while (!stringWalker.IsEof) { if (stringWalker.CurrentCharacter == '\"') { - _ = stringWalker.ReadCharacter(); - break; + if (useVerbatim && stringWalker.NextCharacter == '\"') + { + if (_escapeCharacterList is not null) + { + _escapeCharacterList.Add(new TextEditorTextSpan( + stringWalker.PositionIndex, + stringWalker.PositionIndex + 2, + (byte)GenericDecorationKind.EscapeCharacter, + stringWalker.ResourceUri, + stringWalker.SourceText)); + } + + _ = stringWalker.ReadCharacter(); + } + else + { + _ = stringWalker.ReadCharacter(); + break; + } } - else if (stringWalker.CurrentCharacter == '\\') + else if (!useVerbatim && stringWalker.CurrentCharacter == '\\') { if (_escapeCharacterList is not null) { @@ -254,7 +311,7 @@ private void LexStringInterpolation(StringWalker stringWalker, List syntaxTokenList) - { - var entryPositionIndex = stringWalker.PositionIndex; - - _ = stringWalker.ReadCharacter(); // Move past the '@' (at character) - _ = stringWalker.ReadCharacter(); // Move past the '"' (double quote character) - - while (!stringWalker.IsEof) - { - if (stringWalker.CurrentCharacter == '\"') - { - if (stringWalker.NextCharacter == '\"') - { - if (_escapeCharacterList is not null) - { - _escapeCharacterList.Add(new TextEditorTextSpan( - stringWalker.PositionIndex, - stringWalker.PositionIndex + 2, - (byte)GenericDecorationKind.EscapeCharacter, - stringWalker.ResourceUri, - stringWalker.SourceText)); - } - - _ = stringWalker.ReadCharacter(); - } - else - { - _ = stringWalker.ReadCharacter(); - break; - } - } - - _ = stringWalker.ReadCharacter(); - } - - var textSpan = new TextEditorTextSpan( - entryPositionIndex, - stringWalker.PositionIndex, - (byte)GenericDecorationKind.StringLiteral, - stringWalker.ResourceUri, - stringWalker.SourceText); - - _syntaxTokenList.Add(new StringLiteralToken(textSpan)); - } - private void LexStringRaw(StringWalker stringWalker, List syntaxTokenList) { var entryPositionIndex = stringWalker.PositionIndex; From c0629ffb89a2b7c1e14d16abfc4cb46080c91ede Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:53:09 -0500 Subject: [PATCH 09/21] interpolated raw progress --- .../CSharp/LexerCase/CSharpLexer.cs | 168 ++++++++++-------- 1 file changed, 98 insertions(+), 70 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index a41b269fb..9058ecaad 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -103,17 +103,11 @@ public override void Lex() LexerUtils.LexCharLiteralToken(_stringWalker, _syntaxTokenList, _escapeCharacterList); break; case '"': - if (_stringWalker.PeekCharacter(1) == '"' && _stringWalker.PeekCharacter(2) == '"') - { - // At least 3 double quotes are required for a raw string. - // The actual counting of how many quotes will be used as a deliminator - // is done inside the method. - LexStringRaw(_stringWalker, _syntaxTokenList); - } - else - { - LexerUtils.LexStringLiteralToken(_stringWalker, _syntaxTokenList, _escapeCharacterList); - } + LexString( + _stringWalker, + _syntaxTokenList, + countDollarSign: 1, + useVerbatim: false); break; case '/': if (_stringWalker.PeekCharacter(1) == '/') @@ -188,20 +182,60 @@ public override void Lex() case '$': if (_stringWalker.NextCharacter == '"') { - LexStringEitherInterpolationAndOrVerbatim( + LexString( _stringWalker, _syntaxTokenList, - useInterpolation: true, + countDollarSign: 1, useVerbatim: false); } else if (_stringWalker.PeekCharacter(1) == '@' && _stringWalker.PeekCharacter(2) == '"') { - LexStringEitherInterpolationAndOrVerbatim( + LexString( _stringWalker, _syntaxTokenList, - useInterpolation: true, + countDollarSign: 1, useVerbatim: true); } + else if (_stringWalker.NextCharacter == '$') + { + var entryPositionIndex = _stringWalker.PositionIndex; + + // The while loop starts counting from and including the first dollar sign. + var countDollarSign = 0; + + while (!_stringWalker.IsEof) + { + if (_stringWalker.CurrentCharacter != '$') + break; + + ++countDollarSign; + _ = _stringWalker.ReadCharacter(); + } + + // Only the last '$' (dollar sign character) will be syntax highlighted + // if this code is NOT included. + var textSpan = new TextEditorTextSpan( + entryPositionIndex, + _stringWalker.PositionIndex, + (byte)GenericDecorationKind.StringLiteral, + _stringWalker.ResourceUri, + _stringWalker.SourceText); + _syntaxTokenList.Add(new StringLiteralToken(textSpan)); + + // From the LexString(...) method: + // "awkwardly even if there are many of these it is expected + // that the last one will not have been consumed." + _ = _stringWalker.BacktrackCharacter(); + + if (_stringWalker.NextCharacter == '"') + { + LexString( + _stringWalker, + _syntaxTokenList, + countDollarSign: countDollarSign, + useVerbatim: false); + } + } else { LexerUtils.LexDollarSignToken(_stringWalker, _syntaxTokenList); @@ -210,18 +244,18 @@ public override void Lex() case '@': if (_stringWalker.NextCharacter == '"') { - LexStringEitherInterpolationAndOrVerbatim( + LexString( _stringWalker, _syntaxTokenList, - useInterpolation: false, + countDollarSign: 0, useVerbatim: true); } else if (_stringWalker.PeekCharacter(1) == '$' && _stringWalker.PeekCharacter(2) == '"') { - LexStringEitherInterpolationAndOrVerbatim( + LexString( _stringWalker, _syntaxTokenList, - useInterpolation: true, + countDollarSign: 1, useVerbatim: true); } else @@ -257,16 +291,42 @@ public override void Lex() _syntaxTokenList.Add(new EndOfFileToken(endOfFileTextSpan)); } - private void LexStringEitherInterpolationAndOrVerbatim( + /// + /// The invoker of this method is expected to count the amount of '$' (dollar sign characters). + /// When it comes to raw strings however, this logic will counted inside of this method. + /// + /// The reason being: you don't know if it is a string until you've read all of the '$' (dollar sign characters). + /// So in order to invoke this method the invoker had to have counted them. + /// + private void LexString( StringWalker stringWalker, List syntaxTokenList, - bool useInterpolation, + int countDollarSign, bool useVerbatim) { var entryPositionIndex = stringWalker.PositionIndex; + var useInterpolation = countDollarSign > 0; + var useRaw = false; + int countDoubleQuotes = 0; + + if (stringWalker.PeekCharacter(1) == '\"' && stringWalker.PeekCharacter(2) == '\"') + { + useRaw = true; + + // Count the amount of double quotes to be used as the delimiter. + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter != '\"') + break; + + ++countDoubleQuotes; + _ = stringWalker.ReadCharacter(); + } + } + if (useInterpolation) - _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character) + _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character); awkwardly even if there are many of these it is expected that the last one will not have been consumed. if (useVerbatim) _ = stringWalker.ReadCharacter(); // Move past the '@' (at character) @@ -276,7 +336,20 @@ private void LexStringEitherInterpolationAndOrVerbatim( { if (stringWalker.CurrentCharacter == '\"') { - if (useVerbatim && stringWalker.NextCharacter == '\"') + if (useRaw) + { + var matchDoubleQuotes = countDoubleQuotes; + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter != '\"') + break; + + _ = stringWalker.ReadCharacter(); + if (--matchDoubleQuotes == 0) + goto foundEndDelimiter; + } + } + else if (useVerbatim && stringWalker.NextCharacter == '\"') { if (_escapeCharacterList is not null) { @@ -339,6 +412,8 @@ private void LexStringEitherInterpolationAndOrVerbatim( _ = stringWalker.ReadCharacter(); } + foundEndDelimiter: + var textSpan = new TextEditorTextSpan( entryPositionIndex, stringWalker.PositionIndex, @@ -374,51 +449,4 @@ private void LexInterpolatedExpression(StringWalker stringWalker, List syntaxTokenList) - { - var entryPositionIndex = stringWalker.PositionIndex; - - int countDoubleQuotes = 0; - - // Count the amount of double quotes to be used as the delimiter. - while (!stringWalker.IsEof) - { - if (stringWalker.CurrentCharacter != '\"') - break; - - ++countDoubleQuotes; - _ = stringWalker.ReadCharacter(); - } - - while (!stringWalker.IsEof) - { - if (stringWalker.CurrentCharacter == '\"') - { - var matchDoubleQuotes = countDoubleQuotes; - while (!stringWalker.IsEof) - { - if (stringWalker.CurrentCharacter != '\"') - break; - - _ = stringWalker.ReadCharacter(); - if (--matchDoubleQuotes == 0) - goto foundEndDelimiter; - } - } - - _ = stringWalker.ReadCharacter(); - } - - foundEndDelimiter: - - var textSpan = new TextEditorTextSpan( - entryPositionIndex, - stringWalker.PositionIndex, - (byte)GenericDecorationKind.StringLiteral, - stringWalker.ResourceUri, - stringWalker.SourceText); - - _syntaxTokenList.Add(new StringLiteralToken(textSpan)); - } } \ No newline at end of file From 665d03ee8756c585ec0b8737d404860c4a822b76 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:42:42 -0500 Subject: [PATCH 10/21] Single interpolation raw string case --- .../CSharp/LexerCase/CSharpLexer.cs | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 9058ecaad..1fd4e4bb7 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -106,7 +106,7 @@ public override void Lex() LexString( _stringWalker, _syntaxTokenList, - countDollarSign: 1, + countDollarSign: 0, useVerbatim: false); break; case '/': @@ -307,10 +307,16 @@ private void LexString( var entryPositionIndex = stringWalker.PositionIndex; var useInterpolation = countDollarSign > 0; + + if (useInterpolation) + _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character); awkwardly even if there are many of these it is expected that the last one will not have been consumed. + if (useVerbatim) + _ = stringWalker.ReadCharacter(); // Move past the '@' (at character) + var useRaw = false; int countDoubleQuotes = 0; - - if (stringWalker.PeekCharacter(1) == '\"' && stringWalker.PeekCharacter(2) == '\"') + + if (!useVerbatim && stringWalker.PeekCharacter(1) == '\"' && stringWalker.PeekCharacter(2) == '\"') { useRaw = true; @@ -324,13 +330,10 @@ private void LexString( _ = stringWalker.ReadCharacter(); } } - - if (useInterpolation) - _ = stringWalker.ReadCharacter(); // Move past the '$' (dollar sign character); awkwardly even if there are many of these it is expected that the last one will not have been consumed. - if (useVerbatim) - _ = stringWalker.ReadCharacter(); // Move past the '@' (at character) - - _ = stringWalker.ReadCharacter(); // Move past the '"' (double quote character) + else + { + _ = stringWalker.ReadCharacter(); // Move past the '"' (double quote character) + } while (!stringWalker.IsEof) { @@ -338,16 +341,19 @@ private void LexString( { if (useRaw) { - var matchDoubleQuotes = countDoubleQuotes; + var matchDoubleQuotes = 0; + while (!stringWalker.IsEof) { if (stringWalker.CurrentCharacter != '\"') break; _ = stringWalker.ReadCharacter(); - if (--matchDoubleQuotes == 0) + if (++matchDoubleQuotes == countDoubleQuotes) goto foundEndDelimiter; } + + continue; } else if (useVerbatim && stringWalker.NextCharacter == '\"') { From d1b45a4a51bc117d7afdeb735e2fc594fc272cee Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:33:30 -0500 Subject: [PATCH 11/21] Interpolation and raw mixtures --- .../CSharp/LexerCase/CSharpLexer.cs | 84 ++++++++++++++----- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 1fd4e4bb7..44e3af551 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -392,26 +392,72 @@ private void LexString( } else if (useInterpolation && stringWalker.CurrentCharacter == '{') { - if (stringWalker.NextCharacter == '{') + // With raw, one is escaping by way of typing less. + // With normal interpolation, one is escaping by way of typing more. + // + // Thus, these are two separate cases written as an if-else. + if (useRaw) { - _ = stringWalker.ReadCharacter(); + var interpolationTemporaryPositionIndex = stringWalker.PositionIndex; + var matchBrace = 0; + + while (!stringWalker.IsEof) + { + if (stringWalker.CurrentCharacter != '{') + break; + + _ = stringWalker.ReadCharacter(); + if (++matchBrace >= countDollarSign) + { + // Found yet another '{' match beyond what was needed. + // So, this logic will match from the inside to the outside. + if (stringWalker.CurrentCharacter == '{') + { + ++interpolationTemporaryPositionIndex; + } + else + { + var innerTextSpan = new TextEditorTextSpan( + entryPositionIndex, + interpolationTemporaryPositionIndex, + (byte)GenericDecorationKind.StringLiteral, + stringWalker.ResourceUri, + stringWalker.SourceText); + _syntaxTokenList.Add(new StringLiteralToken(innerTextSpan)); + + // 'LexInterpolatedExpression' is expected to consume one more after it is finished. + // Thus, if this while loop were to consume, it would skip the + // closing double quotes if the expression were the last thing in the string. + LexInterpolatedExpression(stringWalker, syntaxTokenList, countDollarSign); + entryPositionIndex = stringWalker.PositionIndex; + break; + } + } + } } else { - var innerTextSpan = new TextEditorTextSpan( - entryPositionIndex, - stringWalker.PositionIndex, - (byte)GenericDecorationKind.StringLiteral, - stringWalker.ResourceUri, - stringWalker.SourceText); - _syntaxTokenList.Add(new StringLiteralToken(innerTextSpan)); - - // 'LexInterpolatedExpression' is expected to consume one more after it is finished. - // Thus, if this while loop were to consume, it would skip the - // closing double quotes if the expression were the last thing in the string. - LexInterpolatedExpression(stringWalker, syntaxTokenList); - entryPositionIndex = stringWalker.PositionIndex; - continue; + if (stringWalker.NextCharacter == '{') + { + _ = stringWalker.ReadCharacter(); + } + else + { + var innerTextSpan = new TextEditorTextSpan( + entryPositionIndex, + stringWalker.PositionIndex, + (byte)GenericDecorationKind.StringLiteral, + stringWalker.ResourceUri, + stringWalker.SourceText); + _syntaxTokenList.Add(new StringLiteralToken(innerTextSpan)); + + // 'LexInterpolatedExpression' is expected to consume one more after it is finished. + // Thus, if this while loop were to consume, it would skip the + // closing double quotes if the expression were the last thing in the string. + LexInterpolatedExpression(stringWalker, syntaxTokenList, countDollarSign); + entryPositionIndex = stringWalker.PositionIndex; + continue; + } } } @@ -430,13 +476,13 @@ private void LexString( _syntaxTokenList.Add(new StringLiteralToken(textSpan)); } - private void LexInterpolatedExpression(StringWalker stringWalker, List syntaxTokenList) + private void LexInterpolatedExpression(StringWalker stringWalker, List syntaxTokenList, int countDollarSign) { var entryPositionIndex = stringWalker.PositionIndex; - + _ = stringWalker.ReadCharacter(); // Move past the '{' (open brace character) - var unmatchedBraceCounter = 1; + var unmatchedBraceCounter = countDollarSign; while (!stringWalker.IsEof) { From 50088b07469df92c67a2f527f08ce7d3fa522371 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:42:31 -0500 Subject: [PATCH 12/21] Raw string final content is interpolated bug fix --- .../CSharp/LexerCase/CSharpLexer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 44e3af551..2ac7e557d 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -428,9 +428,11 @@ private void LexString( // 'LexInterpolatedExpression' is expected to consume one more after it is finished. // Thus, if this while loop were to consume, it would skip the // closing double quotes if the expression were the last thing in the string. + // + // So, a backtrack is done. LexInterpolatedExpression(stringWalker, syntaxTokenList, countDollarSign); entryPositionIndex = stringWalker.PositionIndex; - break; + stringWalker.BacktrackCharacter(); } } } @@ -480,7 +482,14 @@ private void LexInterpolatedExpression(StringWalker stringWalker, List Date: Wed, 4 Dec 2024 15:56:57 -0500 Subject: [PATCH 13/21] Alternate escape character syntax highlighting (progress) --- .../CSharp/LexerCase/CSharpLexer.cs | 26 ++++++++++++++++--- .../Decoration/GenericDecorationKind.cs | 3 ++- .../Decoration/GenericDecorationMapper.cs | 3 ++- .../Implementations/LexerUtils.cs | 4 +-- .../TextEditor/wwwroot/luthetusTextEditor.css | 8 ++++++ 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 2ac7e557d..75a46d600 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -359,10 +359,10 @@ private void LexString( { if (_escapeCharacterList is not null) { - _escapeCharacterList.Add(new TextEditorTextSpan( + EscapeCharacterListAdd(new TextEditorTextSpan( stringWalker.PositionIndex, stringWalker.PositionIndex + 2, - (byte)GenericDecorationKind.EscapeCharacter, + (byte)GenericDecorationKind.EscapeCharacterPrimary, stringWalker.ResourceUri, stringWalker.SourceText)); } @@ -379,10 +379,10 @@ private void LexString( { if (_escapeCharacterList is not null) { - _escapeCharacterList.Add(new TextEditorTextSpan( + EscapeCharacterListAdd(new TextEditorTextSpan( stringWalker.PositionIndex, stringWalker.PositionIndex + 2, - (byte)GenericDecorationKind.EscapeCharacter, + (byte)GenericDecorationKind.EscapeCharacterPrimary, stringWalker.ResourceUri, stringWalker.SourceText)); } @@ -510,4 +510,22 @@ private void LexInterpolatedExpression(StringWalker stringWalker, List 0) + { + var lastEntry = _escapeCharacterList[^1]; + + if (lastEntry.EndingIndexExclusive == textSpan.StartingIndexInclusive) + { + textSpan = textSpan with + { + DecorationByte = (byte)GenericDecorationKind.EscapeCharacterSecondary, + }; + } + } + + _escapeCharacterList.Add(textSpan); + } } \ No newline at end of file diff --git a/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationKind.cs b/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationKind.cs index 4dd7f7a43..61c016535 100644 --- a/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationKind.cs +++ b/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationKind.cs @@ -8,7 +8,8 @@ public enum GenericDecorationKind CommentSingleLine, CommentMultiLine, Error, - EscapeCharacter, + EscapeCharacterPrimary, // Two consecutive escape characters can be visually distinct by alternating this and 'EscapeCharacterSecondary' + EscapeCharacterSecondary, // Two consecutive escape characters can be visually distinct by alternating this and 'EscapeCharacterPrimary' StringLiteral, Variable, Function, diff --git a/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs b/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs index 4209dadda..87a10ad82 100644 --- a/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs +++ b/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs @@ -13,7 +13,8 @@ public string Map(byte decorationByte) GenericDecorationKind.None => string.Empty, GenericDecorationKind.Keyword => "luth_te_keyword", GenericDecorationKind.KeywordControl => "luth_te_keyword-control", - GenericDecorationKind.EscapeCharacter => "luth_te_string-literal-escape-character", + GenericDecorationKind.EscapeCharacterPrimary => "luth_te_string-literal-escape-character", + GenericDecorationKind.EscapeCharacterSecondary => "luth_te_string-literal-escape-character luth_te_string-literal-escape-character-secondary", GenericDecorationKind.StringLiteral => "luth_te_string-literal", GenericDecorationKind.Variable => "luth_te_variable", GenericDecorationKind.CommentSingleLine => "luth_te_comment", diff --git a/Source/Lib/TextEditor/CompilerServices/Implementations/LexerUtils.cs b/Source/Lib/TextEditor/CompilerServices/Implementations/LexerUtils.cs index 55f1df8b4..ab07753c7 100644 --- a/Source/Lib/TextEditor/CompilerServices/Implementations/LexerUtils.cs +++ b/Source/Lib/TextEditor/CompilerServices/Implementations/LexerUtils.cs @@ -82,7 +82,7 @@ public static void LexCharLiteralToken( escapeCharacterList.Add(new TextEditorTextSpan( stringWalker.PositionIndex, stringWalker.PositionIndex + 2, - (byte)GenericDecorationKind.EscapeCharacter, + (byte)GenericDecorationKind.EscapeCharacterPrimary, stringWalker.ResourceUri, stringWalker.SourceText)); } @@ -127,7 +127,7 @@ public static void LexStringLiteralToken( escapeCharacterList.Add(new TextEditorTextSpan( stringWalker.PositionIndex, stringWalker.PositionIndex + 2, - (byte)GenericDecorationKind.EscapeCharacter, + (byte)GenericDecorationKind.EscapeCharacterPrimary, stringWalker.ResourceUri, stringWalker.SourceText)); } diff --git a/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css b/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css index 427e561b1..f0ea7b65a 100644 --- a/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css +++ b/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css @@ -51,6 +51,10 @@ color: var(--luth_te_string-literal-escape-character-foreground-color); } +.luth_te_string-literal-escape-character-secondary { + color: var(--luth_te_string-literal-escape-character-secondary-foreground-color); +} + .luth_te_keyword { color: var(--luth_te_keyword-foreground-color); } @@ -535,6 +539,7 @@ --luth_te_variable-foreground-color: rgb(31, 55, 127); --luth_te_string-literal-foreground-color: rgb(163, 21, 21); --luth_te_string-literal-escape-character-foreground-color: rgb(183, 118, 251); + --luth_te_string-literal-escape-character-secondary-foreground-color: var(--luth_te_associated-key-color); --luth_te_keyword-foreground-color: rgb(0, 0, 255); --luth_te_keyword-control-foreground-color: rgb(143, 8, 196); --luth_te_comment-foreground-color: rgb(0, 128, 0); @@ -620,6 +625,7 @@ --luth_te_variable-foreground-color: rgb(156, 220, 254); --luth_te_string-literal-foreground-color: rgb(206, 145, 120); --luth_te_string-literal-escape-character-foreground-color: rgb(215, 186, 125); + --luth_te_string-literal-escape-character-secondary-foreground-color: var(--luth_te_associated-key-color); --luth_te_keyword-foreground-color: rgb(86, 156, 214); --luth_te_keyword-control-foreground-color: rgb(197, 134, 192); --luth_te_comment-foreground-color: rgb(106, 153, 85); @@ -705,6 +711,7 @@ --luth_te_variable-foreground-color: rgb(170, 150, 215); --luth_te_string-literal-foreground-color: rgb(190, 190, 60); --luth_te_string-literal-escape-character-foreground-color: rgb(86, 156, 255); + --luth_te_string-literal-escape-character-secondary-foreground-color: var(--luth_te_associated-key-color); --luth_te_keyword-foreground-color: rgb(215, 150, 70); --luth_te_keyword-control-foreground-color: rgb(215, 100, 100); --luth_te_comment-foreground-color: rgb(142, 142, 142); @@ -790,6 +797,7 @@ --luth_te_variable-foreground-color: rgb(0, 128, 0); --luth_te_string-literal-foreground-color: rgb(0,100,180); --luth_te_string-literal-escape-character-foreground-color: rgb(140, 0, 140); + --luth_te_string-literal-escape-character-secondary-foreground-color: var(--luth_te_associated-key-color); --luth_te_keyword-foreground-color: rgb(170,0,250); --luth_te_keyword-control-foreground-color: rgb(215,0,0); --luth_te_comment-foreground-color: rgb(120, 120, 120); From 5fd364752138925b209ecddf923328ef7ebd3f29 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:08:28 -0500 Subject: [PATCH 14/21] Alternate colors for contiguous escape characters --- Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs | 6 +++++- Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 75a46d600..438c35208 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -20,6 +20,8 @@ public CSharpLexer(ResourceUri resourceUri, string sourceText) new LexerKeywords(CSharpKeywords.NON_CONTEXTUAL_KEYWORDS, CSharpKeywords.CONTROL_KEYWORDS, CSharpKeywords.CONTEXTUAL_KEYWORDS)) { } + + private byte _decorationByteLastEscapeCharacter = (byte)GenericDecorationKind.None; public ImmutableArray EscapeCharacterList => _escapeCharacterList.ToImmutableArray(); @@ -517,7 +519,8 @@ private void EscapeCharacterListAdd(TextEditorTextSpan textSpan) { var lastEntry = _escapeCharacterList[^1]; - if (lastEntry.EndingIndexExclusive == textSpan.StartingIndexInclusive) + if (lastEntry.EndingIndexExclusive == textSpan.StartingIndexInclusive && + _decorationByteLastEscapeCharacter == (byte)GenericDecorationKind.EscapeCharacterPrimary) { textSpan = textSpan with { @@ -526,6 +529,7 @@ private void EscapeCharacterListAdd(TextEditorTextSpan textSpan) } } + _decorationByteLastEscapeCharacter = textSpan.DecorationByte; _escapeCharacterList.Add(textSpan); } } \ No newline at end of file diff --git a/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css b/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css index f0ea7b65a..5ea3e8b41 100644 --- a/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css +++ b/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css @@ -711,7 +711,7 @@ --luth_te_variable-foreground-color: rgb(170, 150, 215); --luth_te_string-literal-foreground-color: rgb(190, 190, 60); --luth_te_string-literal-escape-character-foreground-color: rgb(86, 156, 255); - --luth_te_string-literal-escape-character-secondary-foreground-color: var(--luth_te_associated-key-color); + --luth_te_string-literal-escape-character-secondary-foreground-color: rgb(230, 110, 160); --luth_te_keyword-foreground-color: rgb(215, 150, 70); --luth_te_keyword-control-foreground-color: rgb(215, 100, 100); --luth_te_comment-foreground-color: rgb(142, 142, 142); From bd41102b3aaf9f26ac01718f1b8436213d2eeb16 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:30:53 -0500 Subject: [PATCH 15/21] List EscapeCharacterList instead of ImmutableArray --- .../CSharp/CompilerServiceCase/CSharpResource.cs | 2 +- .../CSharp/LexerCase/CSharpLexer.cs | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs b/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs index cb4b84435..e1a687b71 100644 --- a/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs +++ b/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs @@ -11,7 +11,7 @@ public CSharpResource(ResourceUri resourceUri, CSharpCompilerService cSharpCompi { } - public ImmutableArray EscapeCharacterList { get; internal set; } + public List EscapeCharacterList { get; internal set; } public override ImmutableArray GetTokenTextSpans() { diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs index 438c35208..2b6796398 100644 --- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs +++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs @@ -11,8 +11,6 @@ namespace Luthetus.CompilerServices.CSharp.LexerCase; public class CSharpLexer : Lexer { - private readonly List _escapeCharacterList = new(); - public CSharpLexer(ResourceUri resourceUri, string sourceText) : base( resourceUri, @@ -23,7 +21,7 @@ public CSharpLexer(ResourceUri resourceUri, string sourceText) private byte _decorationByteLastEscapeCharacter = (byte)GenericDecorationKind.None; - public ImmutableArray EscapeCharacterList => _escapeCharacterList.ToImmutableArray(); + public List EscapeCharacterList { get; } = new(); public override void Lex() { @@ -102,7 +100,7 @@ public override void Lex() LexerUtils.LexNumericLiteralToken(_stringWalker, _syntaxTokenList); break; case '\'': - LexerUtils.LexCharLiteralToken(_stringWalker, _syntaxTokenList, _escapeCharacterList); + LexerUtils.LexCharLiteralToken(_stringWalker, _syntaxTokenList, EscapeCharacterList); break; case '"': LexString( @@ -359,7 +357,7 @@ private void LexString( } else if (useVerbatim && stringWalker.NextCharacter == '\"') { - if (_escapeCharacterList is not null) + if (EscapeCharacterList is not null) { EscapeCharacterListAdd(new TextEditorTextSpan( stringWalker.PositionIndex, @@ -379,7 +377,7 @@ private void LexString( } else if (!useVerbatim && stringWalker.CurrentCharacter == '\\') { - if (_escapeCharacterList is not null) + if (EscapeCharacterList is not null) { EscapeCharacterListAdd(new TextEditorTextSpan( stringWalker.PositionIndex, @@ -515,9 +513,9 @@ private void LexInterpolatedExpression(StringWalker stringWalker, List 0) + if (EscapeCharacterList.Count > 0) { - var lastEntry = _escapeCharacterList[^1]; + var lastEntry = EscapeCharacterList[^1]; if (lastEntry.EndingIndexExclusive == textSpan.StartingIndexInclusive && _decorationByteLastEscapeCharacter == (byte)GenericDecorationKind.EscapeCharacterPrimary) @@ -530,6 +528,6 @@ private void EscapeCharacterListAdd(TextEditorTextSpan textSpan) } _decorationByteLastEscapeCharacter = textSpan.DecorationByte; - _escapeCharacterList.Add(textSpan); + EscapeCharacterList.Add(textSpan); } } \ No newline at end of file From 401bd2a1c08e6163a78903e5fccc599aa883c953 Mon Sep 17 00:00:00 2001 From: Luthetus <45454132+huntercfreeman@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:16:13 -0500 Subject: [PATCH 16/21] All the speed issues were in 'CSharpBinder.Main.StartBinderSession(ResourceUri resourceUri)' --- .../CSharp/BinderCase/CSharpBinder.Main.cs | 53 ++++++++--------- .../CSharpCompilerService.cs | 6 +- .../CompilerServiceCase/CSharpResource.cs | 6 +- .../CSharp/Facts/CSharpFacts.Namespaces.cs | 8 +-- .../CSharp/ParserCase/CSharpParser.cs | 6 +- .../SyntaxActors/DotNetSolutionParser.cs | 2 +- .../CompilerServiceCase/RazorResource.cs | 8 +-- .../SolutionVisualizationDisplay.razor | 6 +- .../Internals/SolutionVisualizationModel.cs | 6 +- .../Models/TerminalCompilerService.cs | 6 +- .../Terminals/Models/TerminalResource.cs | 14 ++--- .../TextEditorCommandDefaultFunctions.cs | 4 +- .../CompilerServiceResource.cs | 18 +++--- .../Implementations/Binder.cs | 7 +-- .../Implementations/CompilerService.cs | 26 ++++----- .../Implementations/Parser.cs | 6 +- .../CompilerServices/Interfaces/IBinder.cs | 4 +- .../Interfaces/ICompilerService.cs | 12 ++-- .../Interfaces/ICompilerServiceResource.cs | 8 +-- .../CompilerServices/Interfaces/IParser.cs | 2 +- .../Syntax/Nodes/CodeBlockNode.cs | 13 ++--- .../Syntax/Nodes/CompilationUnit.cs | 2 +- .../Syntax/Nodes/NamespaceGroupNode.cs | 4 +- .../Utility/CodeBlockBuilder.cs | 6 +- .../TextEditorPresentationModelCalculation.cs | 2 +- .../Internals/AutocompleteMenu.razor.cs | 5 +- .../Internals/FindOverlayDisplay.razor | 2 +- .../Internals/FindOverlayDisplay.razor.cs | 58 +++++++++++-------- .../PresentationAndSelectionDriver.cs | 14 ++--- .../TextEditorModelModifier.EditMethods.cs | 2 +- 30 files changed, 159 insertions(+), 157 deletions(-) diff --git a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Main.cs b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Main.cs index 8cf77a361..8021d798b 100644 --- a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Main.cs +++ b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Main.cs @@ -46,45 +46,39 @@ public CSharpBinder() // _boundScopes.Add(_globalScope.ResourceUri, new List { _globalScope }); } - public ImmutableDictionary NamespaceGroupNodes => _namespaceGroupNodeMap.ToImmutableDictionary(); - public ImmutableArray Symbols => _symbolDefinitions.Values.SelectMany(x => x.SymbolReferences).Select(x => x.Symbol).ToImmutableArray(); + public IReadOnlyDictionary NamespaceGroupNodes => _namespaceGroupNodeMap; + public ITextEditorSymbol[] Symbols => _symbolDefinitions.Values.SelectMany(x => x.SymbolReferences).Select(x => x.Symbol).ToArray(); public Dictionary SymbolDefinitions => _symbolDefinitions; - public ImmutableDictionary AllTypeDefinitions => _allTypeDefinitions.ToImmutableDictionary(); - public ImmutableArray DiagnosticsList => ImmutableArray.Empty; + public IReadOnlyDictionary AllTypeDefinitions => _allTypeDefinitions; + public TextEditorDiagnostic[] DiagnosticsList => Array.Empty(); - ImmutableArray IBinder.SymbolsList => Symbols - .Select(s => (ITextEditorSymbol)s) - .ToImmutableArray(); + ITextEditorSymbol[] IBinder.SymbolsList => Symbols; /// public IBinderSession StartBinderSession(ResourceUri resourceUri) { foreach (var namespaceGroupNodeKvp in _namespaceGroupNodeMap) { - var keepStatements = namespaceGroupNodeKvp.Value.NamespaceStatementNodeList - .Where(x => x.IdentifierToken.TextSpan.ResourceUri != resourceUri) - .ToImmutableArray(); - - _namespaceGroupNodeMap[namespaceGroupNodeKvp.Key] = - new NamespaceGroupNode( - namespaceGroupNodeKvp.Value.NamespaceString, - keepStatements); + for (int i = namespaceGroupNodeKvp.Value.NamespaceStatementNodeList.Count - 1; i >= 0; i--) + { + var x = namespaceGroupNodeKvp.Value.NamespaceStatementNodeList[i]; + + if (x.IdentifierToken.TextSpan.ResourceUri == resourceUri) + namespaceGroupNodeKvp.Value.NamespaceStatementNodeList.RemoveAt(i); + } } foreach (var symbolDefinition in _symbolDefinitions) { - var keep = symbolDefinition.Value.SymbolReferences - .Where(x => x.Symbol.TextSpan.ResourceUri != resourceUri) - .ToList(); - - _symbolDefinitions[symbolDefinition.Key] = - symbolDefinition.Value with - { - SymbolReferences = keep - }; + for (int i = symbolDefinition.Value.SymbolReferences.Count - 1; i >= 0; i--) + { + var x = symbolDefinition.Value.SymbolReferences[i]; + + if (x.Symbol.TextSpan.ResourceUri == resourceUri) + symbolDefinition.Value.SymbolReferences.RemoveAt(i); + } } - // TODO: Why '_globalScope.IndexKey'? Shouldn't this just be 0, its starting the counter fresh? var cSharpBinderSession = new CSharpBinderSession( resourceUri, this, @@ -330,9 +324,8 @@ public void BindNamespaceStatementNode( if (_namespaceGroupNodeMap.TryGetValue(namespaceString, out var inNamespaceGroupNode)) { - var outNamespaceStatementNodeList = inNamespaceGroupNode.NamespaceStatementNodeList - .Add(namespaceStatementNode) - .ToImmutableArray(); + var outNamespaceStatementNodeList = new List(inNamespaceGroupNode.NamespaceStatementNodeList); + outNamespaceStatementNodeList.Add(namespaceStatementNode); var outNamespaceGroupNode = new NamespaceGroupNode( inNamespaceGroupNode.NamespaceString, @@ -344,7 +337,7 @@ public void BindNamespaceStatementNode( { _namespaceGroupNodeMap.Add(namespaceString, new NamespaceGroupNode( namespaceString, - new NamespaceStatementNode[] { namespaceStatementNode }.ToImmutableArray())); + new List { namespaceStatementNode })); } } @@ -872,7 +865,7 @@ public void ClearStateByResourceUri(ResourceUri resourceUri) { var keepStatements = namespaceGroupNodeKvp.Value.NamespaceStatementNodeList .Where(x => x.IdentifierToken.TextSpan.ResourceUri != resourceUri) - .ToImmutableArray(); + .ToList(); _namespaceGroupNodeMap[namespaceGroupNodeKvp.Key] = new NamespaceGroupNode( diff --git a/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpCompilerService.cs b/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpCompilerService.cs index fe7ec8ffc..d6f881327 100644 --- a/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpCompilerService.cs +++ b/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpCompilerService.cs @@ -58,12 +58,12 @@ public void SetDiagnosticRendererType(Type? diagnosticRendererType) DiagnosticRendererType = diagnosticRendererType; } - public override ImmutableArray GetAutocompleteEntries(string word, TextEditorTextSpan textSpan) + public override List GetAutocompleteEntries(string word, TextEditorTextSpan textSpan) { var boundScope = CSharpBinder.GetScope(null, textSpan); if (boundScope is null) - return ImmutableArray.Empty; + return base._emptyAutocompleteEntryList; var autocompleteEntryList = new List(); @@ -191,7 +191,7 @@ public override ImmutableArray GetAutocompleteEntries(string AddSnippets(autocompleteEntryList, word, textSpan); - return autocompleteEntryList.DistinctBy(x => x.DisplayName).ToImmutableArray(); + return autocompleteEntryList.DistinctBy(x => x.DisplayName).ToList(); } private void AddSnippets(List autocompleteEntryList, string word, TextEditorTextSpan textSpan) diff --git a/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs b/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs index e1a687b71..5e743c3f9 100644 --- a/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs +++ b/Source/Lib/CompilerServices/CSharp/CompilerServiceCase/CSharpResource.cs @@ -11,15 +11,15 @@ public CSharpResource(ResourceUri resourceUri, CSharpCompilerService cSharpCompi { } - public List EscapeCharacterList { get; internal set; } + public IReadOnlyList EscapeCharacterList { get; internal set; } - public override ImmutableArray GetTokenTextSpans() + public override IReadOnlyList GetTokenTextSpans() { var tokenTextSpanList = new List(); tokenTextSpanList.AddRange(SyntaxTokenList.Select(st => st.TextSpan)); tokenTextSpanList.AddRange(EscapeCharacterList); - return tokenTextSpanList.ToImmutableArray(); + return tokenTextSpanList; } } \ No newline at end of file diff --git a/Source/Lib/CompilerServices/CSharp/Facts/CSharpFacts.Namespaces.cs b/Source/Lib/CompilerServices/CSharp/Facts/CSharpFacts.Namespaces.cs index bf0525165..2f0b55145 100644 --- a/Source/Lib/CompilerServices/CSharp/Facts/CSharpFacts.Namespaces.cs +++ b/Source/Lib/CompilerServices/CSharp/Facts/CSharpFacts.Namespaces.cs @@ -21,13 +21,13 @@ public static Dictionary GetInitialBoundNamespaceSta { SystemNamespaceIdentifier, new NamespaceGroupNode(SystemNamespaceIdentifier, - new NamespaceStatementNode[] + new List { new NamespaceStatementNode( new(new(0, 0, 0, ResourceUri.Empty, string.Empty), SyntaxKind.UnrecognizedTokenKeyword), new(new(0, SystemNamespaceIdentifier.Length, 0, ResourceUri.Empty, SystemNamespaceIdentifier)), - new CodeBlockNode(ImmutableArray.Empty)) - }.ToImmutableArray()) + new CodeBlockNode(Array.Empty())) + }) } }; } @@ -37,7 +37,7 @@ public static NamespaceStatementNode GetTopLevelNamespaceStatementNode() return new NamespaceStatementNode( new(new(0, 0, 0, ResourceUri.Empty, string.Empty), SyntaxKind.UnrecognizedTokenKeyword), new(new(0, TopLevelNamespaceIdentifier.Length, 0, ResourceUri.Empty, TopLevelNamespaceIdentifier)), - new CodeBlockNode(ImmutableArray.Empty)); + new CodeBlockNode(Array.Empty())); } } } \ No newline at end of file diff --git a/Source/Lib/CompilerServices/CSharp/ParserCase/CSharpParser.cs b/Source/Lib/CompilerServices/CSharp/ParserCase/CSharpParser.cs index 65f2fb01e..ea66135ac 100644 --- a/Source/Lib/CompilerServices/CSharp/ParserCase/CSharpParser.cs +++ b/Source/Lib/CompilerServices/CSharp/ParserCase/CSharpParser.cs @@ -23,7 +23,7 @@ public CSharpParser(CSharpLexer lexer) BinderSession = (CSharpBinderSession)Binder.StartBinderSession(lexer.ResourceUri); } - public ImmutableArray DiagnosticsList { get; private set; } = ImmutableArray.Empty; + public TextEditorDiagnostic[] DiagnosticsList { get; private set; } = Array.Empty(); public CSharpBinder Binder { get; private set; } public CSharpBinderSession BinderSession { get; private set; } public CSharpLexer Lexer { get; } @@ -253,13 +253,13 @@ public CompilationUnit Parse() Binder.CloseScope(model.TokenWalker.Current.TextSpan, model); } - DiagnosticsList = DiagnosticsList.AddRange(model.DiagnosticBag.ToImmutableArray()); + DiagnosticsList = model.DiagnosticBag.ToArray(); var topLevelStatementsCodeBlock = model.CurrentCodeBlockBuilder.Build( DiagnosticsList .Union(Binder.DiagnosticsList) .Union(Lexer.DiagnosticList) - .ToImmutableArray()); + .ToArray()); Binder.FinalizeBinderSession(BinderSession); return new CompilationUnit( diff --git a/Source/Lib/CompilerServices/DotNetSolution/SyntaxActors/DotNetSolutionParser.cs b/Source/Lib/CompilerServices/DotNetSolution/SyntaxActors/DotNetSolutionParser.cs index 1aa7745ab..e465b881d 100644 --- a/Source/Lib/CompilerServices/DotNetSolution/SyntaxActors/DotNetSolutionParser.cs +++ b/Source/Lib/CompilerServices/DotNetSolution/SyntaxActors/DotNetSolutionParser.cs @@ -32,7 +32,7 @@ public DotNetSolutionParser(DotNetSolutionLexer lexer) _tokenWalker = new TokenWalker(lexer.SyntaxTokenList, _diagnosticBag); } - public ImmutableArray DiagnosticsList => _diagnosticBag.ToImmutableArray(); + public TextEditorDiagnostic[] DiagnosticsList => _diagnosticBag.ToArray(); public DotNetSolutionLexer Lexer { get; } public DotNetSolutionHeader DotNetSolutionHeader => _dotNetSolutionHeader; diff --git a/Source/Lib/CompilerServices/Razor/CompilerServiceCase/RazorResource.cs b/Source/Lib/CompilerServices/Razor/CompilerServiceCase/RazorResource.cs index 081562320..9778c88af 100644 --- a/Source/Lib/CompilerServices/Razor/CompilerServiceCase/RazorResource.cs +++ b/Source/Lib/CompilerServices/Razor/CompilerServiceCase/RazorResource.cs @@ -24,12 +24,12 @@ public RazorResource( public RazorSyntaxTree? RazorSyntaxTree { get; internal set; } public List HtmlSymbols { get; } = new(); - public override ImmutableArray GetSymbols() + public override IReadOnlyList GetSymbols() { var localRazorSyntaxTree = RazorSyntaxTree; if (localRazorSyntaxTree?.SemanticResultRazor is null) - return ImmutableArray.Empty; + return Array.Empty(); var symbols = localRazorSyntaxTree .SemanticResultRazor @@ -40,7 +40,7 @@ public override ImmutableArray GetSymbols() var originalText = _textEditorService.ModelApi.GetAllText(ResourceUri); if (originalText is null) - return ImmutableArray.Empty; + return Array.Empty(); List mappedSymbols = new(); @@ -146,6 +146,6 @@ public override ImmutableArray GetSymbols() } } - return mappedSymbols.ToImmutableArray(); + return mappedSymbols; } } \ No newline at end of file diff --git a/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Displays/SolutionVisualizationDisplay.razor b/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Displays/SolutionVisualizationDisplay.razor index 8d3062234..c4efcd5f3 100644 --- a/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Displays/SolutionVisualizationDisplay.razor +++ b/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Displays/SolutionVisualizationDisplay.razor @@ -7,9 +7,9 @@ @{ var localSolutionVisualizationModel = _solutionVisualizationModel; } -_dotNetSolutionCompilerService.CompilerServiceResources.Length: @_dotNetSolutionCompilerService.CompilerServiceResources.Length -_cSharpProjectCompilerService.CompilerServiceResources.Length: @_cSharpProjectCompilerService.CompilerServiceResources.Length -_cSharpCompilerService.CompilerServiceResources.Length: @_cSharpCompilerService.CompilerServiceResources.Length +_dotNetSolutionCompilerService.CompilerServiceResources.Length: @_dotNetSolutionCompilerService.CompilerServiceResources.Count +_cSharpProjectCompilerService.CompilerServiceResources.Length: @_cSharpProjectCompilerService.CompilerServiceResources.Count +_cSharpCompilerService.CompilerServiceResources.Length: @_cSharpCompilerService.CompilerServiceResources.Count localSolutionVisualizationModel.SolutionVisualizationDrawingList.Count: @localSolutionVisualizationModel.SolutionVisualizationDrawingList.Count
    diff --git a/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Models/Internals/SolutionVisualizationModel.cs b/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Models/Internals/SolutionVisualizationModel.cs index 6b0403f09..702c3089b 100644 --- a/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Models/Internals/SolutionVisualizationModel.cs +++ b/Source/Lib/Extensions/Extensions.DotNet/DotNetSolutions/Models/Internals/SolutionVisualizationModel.cs @@ -149,7 +149,7 @@ private void DrawSolution( } private void DrawProjects( - ImmutableArray cSharpProjectResourceList, + IReadOnlyList cSharpProjectResourceList, SolutionVisualizationModel localSolutionVisualizationModel, int radius, int centerX, @@ -164,7 +164,7 @@ private void DrawProjects( localSolutionVisualizationModel.SolutionVisualizationDrawingRenderCycleList.Add(new List()); - for (int i = 0; i < cSharpProjectResourceList.Length; i++) + for (int i = 0; i < cSharpProjectResourceList.Count; i++) { var cSharpProjectResource = cSharpProjectResourceList[i]; @@ -206,7 +206,7 @@ private void DrawProjects( } private void DrawClasses( - ImmutableArray cSharpResourceList, + IReadOnlyList cSharpResourceList, SolutionVisualizationModel localSolutionVisualizationModel, int radius, int centerX, diff --git a/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalCompilerService.cs b/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalCompilerService.cs index e7ff4f5a0..92f883cbc 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalCompilerService.cs +++ b/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalCompilerService.cs @@ -20,17 +20,17 @@ public TerminalCompilerService( }; } - public override ImmutableArray GetTokenTextSpansFor(ResourceUri resourceUri) + public override IReadOnlyList GetTokenTextSpansFor(ResourceUri resourceUri) { var model = _textEditorService.ModelApi.GetOrDefault(resourceUri); if (model is null) - return ImmutableArray.Empty; + return Array.Empty(); lock (_resourceMapLock) { if (!_resourceMap.ContainsKey(resourceUri)) - return ImmutableArray.Empty; + return Array.Empty(); return _resourceMap[resourceUri].GetTokenTextSpans(); } diff --git a/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalResource.cs b/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalResource.cs index 462a406f1..173db9292 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalResource.cs +++ b/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/TerminalResource.cs @@ -22,27 +22,27 @@ public class TerminalResource : CompilerServiceResource public readonly object UnsafeStateLock = new(); public TerminalResource( - ResourceUri resourceUri, - TerminalCompilerService terminalCompilerService) + ResourceUri resourceUri, + TerminalCompilerService terminalCompilerService) : base(resourceUri, terminalCompilerService) { } - public override ImmutableArray SyntaxTokenList { get; set; } = ImmutableArray.Empty; + public override IReadOnlyList SyntaxTokenList { get; set; } = ImmutableArray.Empty; public List ManualDecorationTextSpanList { get; } = new List(); public List ManualSymbolList { get; } = new List(); - public override ImmutableArray GetTokenTextSpans() + public override IReadOnlyList GetTokenTextSpans() { var tokenTextSpanList = new List(); tokenTextSpanList.AddRange(ManualDecorationTextSpanList); tokenTextSpanList.AddRange(SyntaxTokenList.Select(st => st.TextSpan)); - return tokenTextSpanList.ToImmutableArray(); + return tokenTextSpanList; } - public override ImmutableArray GetSymbols() + public override IReadOnlyList GetSymbols() { - return ManualSymbolList.ToImmutableArray(); + return ManualSymbolList; } } \ No newline at end of file diff --git a/Source/Lib/TextEditor/Commands/Models/Defaults/TextEditorCommandDefaultFunctions.cs b/Source/Lib/TextEditor/Commands/Models/Defaults/TextEditorCommandDefaultFunctions.cs index f136bd9f7..398a56b30 100644 --- a/Source/Lib/TextEditor/Commands/Models/Defaults/TextEditorCommandDefaultFunctions.cs +++ b/Source/Lib/TextEditor/Commands/Models/Defaults/TextEditorCommandDefaultFunctions.cs @@ -1360,7 +1360,7 @@ public static async Task HandleMouseStoppedMovingEventAsync( var symbols = modelModifier.CompilerService.GetSymbolsFor(modelModifier.ResourceUri); var diagnostics = modelModifier.CompilerService.GetDiagnosticsFor(modelModifier.ResourceUri); - if (diagnostics.Length != 0) + if (diagnostics.Count != 0) { foreach (var diagnostic in diagnostics) { @@ -1391,7 +1391,7 @@ public static async Task HandleMouseStoppedMovingEventAsync( } } - if (!foundMatch && symbols.Length != 0) + if (!foundMatch && symbols.Count != 0) { foreach (var symbol in symbols) { diff --git a/Source/Lib/TextEditor/CompilerServices/CompilerServiceResource.cs b/Source/Lib/TextEditor/CompilerServices/CompilerServiceResource.cs index df0e101c0..ba057160d 100644 --- a/Source/Lib/TextEditor/CompilerServices/CompilerServiceResource.cs +++ b/Source/Lib/TextEditor/CompilerServices/CompilerServiceResource.cs @@ -19,34 +19,34 @@ public CompilerServiceResource( public virtual ResourceUri ResourceUri { get; } public virtual ICompilerService CompilerService { get; } public virtual CompilationUnit? CompilationUnit { get; set; } - public virtual ImmutableArray SyntaxTokenList { get; set; } = ImmutableArray.Empty; + public virtual IReadOnlyList SyntaxTokenList { get; set; } = ImmutableArray.Empty; - public virtual ImmutableArray GetTokenTextSpans() + public virtual IReadOnlyList GetTokenTextSpans() { - return SyntaxTokenList.Select(st => st.TextSpan).ToImmutableArray(); + return SyntaxTokenList.Select(st => st.TextSpan).ToArray(); } - public virtual ImmutableArray GetSymbols() + public virtual IReadOnlyList GetSymbols() { var localCompilationUnit = CompilationUnit; if (localCompilationUnit is null) - return ImmutableArray.Empty; + return Array.Empty(); return localCompilationUnit.Binder.SymbolsList .Where(s => s.TextSpan.ResourceUri == ResourceUri) - .ToImmutableArray(); + .ToArray(); } - public virtual ImmutableArray GetDiagnostics() + public virtual IReadOnlyList GetDiagnostics() { var localCompilationUnit = CompilationUnit; if (localCompilationUnit is null) - return ImmutableArray.Empty; + return Array.Empty(); return localCompilationUnit.DiagnosticsList .Where(s => s.TextSpan.ResourceUri == ResourceUri) - .ToImmutableArray(); + .ToArray(); } } diff --git a/Source/Lib/TextEditor/CompilerServices/Implementations/Binder.cs b/Source/Lib/TextEditor/CompilerServices/Implementations/Binder.cs index 2d2010274..223c9d77b 100644 --- a/Source/Lib/TextEditor/CompilerServices/Implementations/Binder.cs +++ b/Source/Lib/TextEditor/CompilerServices/Implementations/Binder.cs @@ -14,10 +14,9 @@ public class Binder : IBinder private readonly Dictionary _binderSessionMap = new(); private readonly object _binderSessionMapLock = new(); - public ImmutableArray DiagnosticsList { get; } = ImmutableArray.Empty; - public ImmutableArray SymbolsList { get; } = ImmutableArray.Empty; - public ImmutableDictionary> ScopeList { get; } = ImmutableDictionary>.Empty; - + public TextEditorDiagnostic[] DiagnosticsList { get; } = Array.Empty(); + public ITextEditorSymbol[] SymbolsList { get; } = Array.Empty(); + public IReadOnlyDictionary> ScopeList { get; } = new Dictionary>(); public TextEditorTextSpan? GetDefinitionTextSpan(TextEditorTextSpan textSpan, ICompilerServiceResource compilerServiceResource) { diff --git a/Source/Lib/TextEditor/CompilerServices/Implementations/CompilerService.cs b/Source/Lib/TextEditor/CompilerServices/Implementations/CompilerService.cs index bb86da7dc..a94d4c16e 100644 --- a/Source/Lib/TextEditor/CompilerServices/Implementations/CompilerService.cs +++ b/Source/Lib/TextEditor/CompilerServices/Implementations/CompilerService.cs @@ -12,6 +12,7 @@ namespace Luthetus.TextEditor.RazorLib.CompilerServices.Implementations; public class CompilerService : ICompilerService { + protected readonly List _emptyAutocompleteEntryList = new(); protected readonly Dictionary _resourceMap = new(); protected readonly object _resourceMapLock = new(); protected readonly ITextEditorService _textEditorService; @@ -42,8 +43,7 @@ public CompilerService(ITextEditorService textEditorService) public virtual Type? SymbolRendererType { get; protected set; } public virtual Type? DiagnosticRendererType { get; protected set; } - public virtual ImmutableArray CompilerServiceResources => - _resourceMap.Values.ToImmutableArray(); + public virtual IReadOnlyList CompilerServiceResources => _resourceMap.Values.ToArray(); public virtual void RegisterResource(ResourceUri resourceUri, bool shouldTriggerResourceWasModified) { @@ -60,7 +60,7 @@ public virtual void RegisterResource(ResourceUri resourceUri, bool shouldTrigger } if (shouldTriggerResourceWasModified) - ResourceWasModified(resourceUri, ImmutableArray.Empty); + ResourceWasModified(resourceUri, Array.Empty()); ResourceRegistered?.Invoke(); } @@ -81,40 +81,40 @@ public virtual void RegisterResource(ResourceUri resourceUri, bool shouldTrigger } } - public virtual ImmutableArray GetTokenTextSpansFor(ResourceUri resourceUri) + public virtual IReadOnlyList GetTokenTextSpansFor(ResourceUri resourceUri) { lock (_resourceMapLock) { if (!_resourceMap.ContainsKey(resourceUri)) - return ImmutableArray.Empty; + return Array.Empty(); return _resourceMap[resourceUri].GetTokenTextSpans(); } } - public virtual ImmutableArray GetSymbolsFor(ResourceUri resourceUri) + public virtual IReadOnlyList GetSymbolsFor(ResourceUri resourceUri) { lock (_resourceMapLock) { if (!_resourceMap.ContainsKey(resourceUri)) - return ImmutableArray.Empty; + return Array.Empty(); return _resourceMap[resourceUri].GetSymbols(); } } - public virtual ImmutableArray GetDiagnosticsFor(ResourceUri resourceUri) + public virtual IReadOnlyList GetDiagnosticsFor(ResourceUri resourceUri) { lock (_resourceMapLock) { if (!_resourceMap.ContainsKey(resourceUri)) - return ImmutableArray.Empty; + return Array.Empty(); return _resourceMap[resourceUri].GetDiagnostics(); } } - public virtual void ResourceWasModified(ResourceUri resourceUri, ImmutableArray editTextSpansList) + public virtual void ResourceWasModified(ResourceUri resourceUri, IReadOnlyList editTextSpansList) { _textEditorService.PostUnique( nameof(CompilerService), @@ -133,9 +133,9 @@ public virtual void CursorWasModified(ResourceUri resourceUri, TextEditorCursor { } - public virtual ImmutableArray GetAutocompleteEntries(string word, TextEditorTextSpan textSpan) + public virtual List GetAutocompleteEntries(string word, TextEditorTextSpan textSpan) { - return ImmutableArray.Empty; + return _emptyAutocompleteEntryList; } public virtual Task ParseAsync(ITextEditorEditContext editContext, TextEditorModelModifier modelModifier) @@ -216,7 +216,7 @@ public virtual Task ParseAsync(ITextEditorEditContext editContext, TextEditorMod var diagnosticTextSpans = GetDiagnosticsFor(modelModifier.ResourceUri) .Select(x => x.TextSpan) - .ToImmutableArray(); + .ToArray(); modelModifier.CompletePendingCalculatePresentationModel( CompilerServiceDiagnosticPresentationFacts.PresentationKey, diff --git a/Source/Lib/TextEditor/CompilerServices/Implementations/Parser.cs b/Source/Lib/TextEditor/CompilerServices/Implementations/Parser.cs index b47d2d03a..b42e6844a 100644 --- a/Source/Lib/TextEditor/CompilerServices/Implementations/Parser.cs +++ b/Source/Lib/TextEditor/CompilerServices/Implementations/Parser.cs @@ -16,7 +16,7 @@ public Parser(ILexer lexer) BinderSession = Binder.StartBinderSession(lexer.ResourceUri); } - public ImmutableArray DiagnosticsList { get; private set; } = ImmutableArray.Empty; + public TextEditorDiagnostic[] DiagnosticsList { get; private set; } = Array.Empty(); public IBinder Binder { get; private set; } public IBinderSession BinderSession { get; private set; } public ILexer Lexer { get; } @@ -47,13 +47,13 @@ public virtual CompilationUnit Parse() globalCodeBlockBuilder, currentCodeBlockBuilder); - DiagnosticsList = DiagnosticsList.AddRange(model.DiagnosticBag.ToImmutableArray()); + DiagnosticsList = model.DiagnosticBag.ToArray(); var topLevelStatementsCodeBlock = model.CurrentCodeBlockBuilder.Build( DiagnosticsList .Union(Binder.DiagnosticsList) .Union(Lexer.DiagnosticList) - .ToImmutableArray()); + .ToArray()); return new CompilationUnit( topLevelStatementsCodeBlock, diff --git a/Source/Lib/TextEditor/CompilerServices/Interfaces/IBinder.cs b/Source/Lib/TextEditor/CompilerServices/Interfaces/IBinder.cs index e4533b116..f7c9626e3 100644 --- a/Source/Lib/TextEditor/CompilerServices/Interfaces/IBinder.cs +++ b/Source/Lib/TextEditor/CompilerServices/Interfaces/IBinder.cs @@ -9,8 +9,8 @@ namespace Luthetus.TextEditor.RazorLib.CompilerServices.Interfaces; public interface IBinder { - public ImmutableArray DiagnosticsList { get; } - public ImmutableArray SymbolsList { get; } + public TextEditorDiagnostic[] DiagnosticsList { get; } + public ITextEditorSymbol[] SymbolsList { get; } /// /// Returns the text span at which the definition exists in the source code. diff --git a/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerService.cs b/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerService.cs index c414afca1..2ec3cb6cd 100644 --- a/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerService.cs +++ b/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerService.cs @@ -12,7 +12,7 @@ public interface ICompilerService public event Action? ResourceParsed; public event Action? ResourceDisposed; - public ImmutableArray CompilerServiceResources { get; } + public IReadOnlyList CompilerServiceResources { get; } public IBinder? Binder { get; } /// @@ -53,7 +53,7 @@ public interface ICompilerService public void RegisterResource(ResourceUri resourceUri, bool shouldTriggerResourceWasModified); /// Expected to be an (or anything which performs background task work) - public void ResourceWasModified(ResourceUri resourceUri, ImmutableArray editTextSpansList); + public void ResourceWasModified(ResourceUri resourceUri, IReadOnlyList editTextSpansList); public ICompilerServiceResource? GetCompilerServiceResourceFor(ResourceUri resourceUri); @@ -67,25 +67,25 @@ public interface ICompilerService /// Provides syntax highlighting from the lexing result. /// This method is invoked, and applied, before /// - public ImmutableArray GetTokenTextSpansFor(ResourceUri resourceUri); + public IReadOnlyList GetTokenTextSpansFor(ResourceUri resourceUri); /// /// Provides syntax highlighting that cannot be determined by lexing alone. /// This method is invoked, and applied, after /// - public ImmutableArray GetSymbolsFor(ResourceUri resourceUri); + public IReadOnlyList GetSymbolsFor(ResourceUri resourceUri); /// /// Provides 'squigglies' which when hovered over display a message, along with /// a serverity level. /// - public ImmutableArray GetDiagnosticsFor(ResourceUri resourceUri); + public IReadOnlyList GetDiagnosticsFor(ResourceUri resourceUri); /// /// When a user types a period ('.') or hits the keybind: { 'Ctrl' + 'Space' } /// this method is invoked to populate the autocomplete menu. /// - public ImmutableArray GetAutocompleteEntries(string word, TextEditorTextSpan textSpan); + public List GetAutocompleteEntries(string word, TextEditorTextSpan textSpan); public Task ParseAsync(ITextEditorEditContext editContext, TextEditorModelModifier modelModifier); diff --git a/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerServiceResource.cs b/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerServiceResource.cs index 4a8785f9c..a351e26ad 100644 --- a/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerServiceResource.cs +++ b/Source/Lib/TextEditor/CompilerServices/Interfaces/ICompilerServiceResource.cs @@ -10,9 +10,9 @@ public interface ICompilerServiceResource public ResourceUri ResourceUri { get; } public ICompilerService CompilerService { get; } public CompilationUnit? CompilationUnit { get; set; } - public ImmutableArray SyntaxTokenList { get; set; } + public IReadOnlyList SyntaxTokenList { get; set; } - public ImmutableArray GetTokenTextSpans(); - public ImmutableArray GetSymbols(); - public ImmutableArray GetDiagnostics(); + public IReadOnlyList GetTokenTextSpans(); + public IReadOnlyList GetSymbols(); + public IReadOnlyList GetDiagnostics(); } diff --git a/Source/Lib/TextEditor/CompilerServices/Interfaces/IParser.cs b/Source/Lib/TextEditor/CompilerServices/Interfaces/IParser.cs index 6b992e8b3..df0979be9 100644 --- a/Source/Lib/TextEditor/CompilerServices/Interfaces/IParser.cs +++ b/Source/Lib/TextEditor/CompilerServices/Interfaces/IParser.cs @@ -6,7 +6,7 @@ namespace Luthetus.TextEditor.RazorLib.CompilerServices.Interfaces; public interface IParser { - public ImmutableArray DiagnosticsList { get; } + public TextEditorDiagnostic[] DiagnosticsList { get; } public IBinder Binder { get; } public IBinderSession BinderSession { get; } public ILexer Lexer { get; } diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CodeBlockNode.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CodeBlockNode.cs index 6b43405f0..a278d9546 100644 --- a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CodeBlockNode.cs +++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CodeBlockNode.cs @@ -9,16 +9,15 @@ namespace Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Nodes; /// public sealed class CodeBlockNode : ISyntaxNode { - public CodeBlockNode(ImmutableArray childList) + public CodeBlockNode(ISyntax[] childList) { - _childList = childList.ToArray(); - - DiagnosticsList = ImmutableArray.Empty; + _childList = childList; + DiagnosticsList = Array.Empty(); } public CodeBlockNode( - ImmutableArray childList, - ImmutableArray diagnostics) + ISyntax[] childList, + TextEditorDiagnostic[] diagnostics) { _childList = childList.ToArray(); DiagnosticsList = diagnostics; @@ -27,7 +26,7 @@ public CodeBlockNode( private ISyntax[] _childList = Array.Empty(); private bool _childListIsDirty = true; - public ImmutableArray DiagnosticsList { get; init; } + public TextEditorDiagnostic[] DiagnosticsList { get; init; } public bool IsFabricated { get; init; } public SyntaxKind SyntaxKind => SyntaxKind.CodeBlockNode; diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CompilationUnit.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CompilationUnit.cs index 7adcd859d..b15f29c6e 100644 --- a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CompilationUnit.cs +++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/CompilationUnit.cs @@ -18,7 +18,7 @@ public CompilationUnit( IParser? parser, IBinder? binder) { - RootCodeBlockNode = rootCodeBlockNode ?? new CodeBlockNode(ImmutableArray.Empty); + RootCodeBlockNode = rootCodeBlockNode ?? new CodeBlockNode(Array.Empty()); Lexer = lexer ?? new Lexer(ResourceUri.Empty, null, null); Parser = parser ?? new Parser(Lexer); Binder = binder ?? new Binder(); diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/NamespaceGroupNode.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/NamespaceGroupNode.cs index 180fe5455..1b57920ac 100644 --- a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/NamespaceGroupNode.cs +++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/NamespaceGroupNode.cs @@ -6,7 +6,7 @@ public sealed class NamespaceGroupNode : ISyntaxNode { public NamespaceGroupNode( string namespaceString, - ImmutableArray namespaceStatementNodeList) + List namespaceStatementNodeList) { NamespaceString = namespaceString; NamespaceStatementNodeList = namespaceStatementNodeList; @@ -16,7 +16,7 @@ public NamespaceGroupNode( private bool _childListIsDirty = true; public string NamespaceString { get; } - public ImmutableArray NamespaceStatementNodeList { get; } = ImmutableArray.Empty; + public List NamespaceStatementNodeList { get; } public bool IsFabricated { get; init; } public SyntaxKind SyntaxKind => SyntaxKind.NamespaceGroupNode; diff --git a/Source/Lib/TextEditor/CompilerServices/Utility/CodeBlockBuilder.cs b/Source/Lib/TextEditor/CompilerServices/Utility/CodeBlockBuilder.cs index 4a3ab9979..a39008174 100644 --- a/Source/Lib/TextEditor/CompilerServices/Utility/CodeBlockBuilder.cs +++ b/Source/Lib/TextEditor/CompilerServices/Utility/CodeBlockBuilder.cs @@ -56,11 +56,11 @@ public CodeBlockBuilder(CodeBlockBuilder? parent, ICodeBlockOwner? codeBlockOwne public CodeBlockNode Build() { - return new CodeBlockNode(ChildList.ToImmutableArray()); + return new CodeBlockNode(ChildList.ToArray()); } - public CodeBlockNode Build(ImmutableArray diagnostics) + public CodeBlockNode Build(TextEditorDiagnostic[] diagnostics) { - return new CodeBlockNode(ChildList.ToImmutableArray(), diagnostics); + return new CodeBlockNode(ChildList.ToArray(), diagnostics); } } \ No newline at end of file diff --git a/Source/Lib/TextEditor/Decorations/Models/TextEditorPresentationModelCalculation.cs b/Source/Lib/TextEditor/Decorations/Models/TextEditorPresentationModelCalculation.cs index 71bac18d6..b7ad52da0 100644 --- a/Source/Lib/TextEditor/Decorations/Models/TextEditorPresentationModelCalculation.cs +++ b/Source/Lib/TextEditor/Decorations/Models/TextEditorPresentationModelCalculation.cs @@ -10,5 +10,5 @@ namespace Luthetus.TextEditor.RazorLib.Decorations.Models; public record TextEditorPresentationModelCalculation(string ContentAtRequest) { public List TextModificationsSinceRequestList { get; set; } = new(); - public ImmutableArray TextSpanList { get; set; } = ImmutableArray.Empty; + public IReadOnlyList TextSpanList { get; set; } = Array.Empty(); } \ No newline at end of file diff --git a/Source/Lib/TextEditor/TextEditors/Displays/Internals/AutocompleteMenu.razor.cs b/Source/Lib/TextEditor/TextEditors/Displays/Internals/AutocompleteMenu.razor.cs index 473614deb..8818dc495 100644 --- a/Source/Lib/TextEditor/TextEditors/Displays/Internals/AutocompleteMenu.razor.cs +++ b/Source/Lib/TextEditor/TextEditors/Displays/Internals/AutocompleteMenu.razor.cs @@ -165,9 +165,8 @@ private MenuRecord GetMenuRecord() if (compilerServiceAutocompleteEntryList.Any()) { - autocompleteEntryList = compilerServiceAutocompleteEntryList - .AddRange(autocompleteEntryList) - .ToArray(); + compilerServiceAutocompleteEntryList + .AddRange(autocompleteEntryList); } } diff --git a/Source/Lib/TextEditor/TextEditors/Displays/Internals/FindOverlayDisplay.razor b/Source/Lib/TextEditor/TextEditors/Displays/Internals/FindOverlayDisplay.razor index e2923925f..63a296c26 100644 --- a/Source/Lib/TextEditor/TextEditors/Displays/Internals/FindOverlayDisplay.razor +++ b/Source/Lib/TextEditor/TextEditors/Displays/Internals/FindOverlayDisplay.razor @@ -62,7 +62,7 @@ of - @completedCalculation.TextSpanList.Length + @completedCalculation.TextSpanList.Count